#Lab: Dockerfile Optimization
Reduce image size and improve build performance.
#๐ฏ Objectives
- Implement multi-stage builds
- Minimize image layers
- Choose optimal base images
- Measure size improvements
#๐ Prerequisites
- Docker installed
#โฑ๏ธ Duration: 30 minutes
#Task 1: Measure Baseline (5 min)
Create an unoptimized Dockerfile:
bash
1mkdir ~/optimize-lab && cd ~/optimize-lab
2
3cat << 'EOF' > app.go
4package main
5import "fmt"
6func main() { fmt.Println("Hello, Docker!") }
7EOF
8
9# Unoptimized Dockerfile
10cat << 'EOF' > Dockerfile.unoptimized
11FROM golang:1.21
12WORKDIR /app
13COPY . .
14RUN go build -o app
15CMD ["./app"]
16EOF
17
18docker build -t app:unoptimized -f Dockerfile.unoptimized .
19docker images app:unoptimizedNote the image size (~800MB+).
#Task 2: Multi-Stage Build (10 min)
bash
1cat << 'EOF' > Dockerfile.multistage
2# Build stage
3FROM golang:1.21-alpine AS builder
4WORKDIR /app
5COPY . .
6RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o app
7
8# Runtime stage
9FROM alpine:3.18
10COPY --from=builder /app/app /app
11ENTRYPOINT ["/app"]
12EOF
13
14docker build -t app:multistage -f Dockerfile.multistage .
15docker images app:multistageCompare sizes:
bash
docker images | grep "app"#Task 3: Scratch Base (5 min)
bash
1cat << 'EOF' > Dockerfile.scratch
2FROM golang:1.21-alpine AS builder
3WORKDIR /app
4COPY . .
5RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o app
6
7FROM scratch
8COPY --from=builder /app/app /app
9ENTRYPOINT ["/app"]
10EOF
11
12docker build -t app:scratch -f Dockerfile.scratch .
13docker images app:scratch#Task 4: Compare All Sizes (5 min)
bash
echo "=== Image Size Comparison ==="
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}" | grep "app:"Expected results:
| Image | Approximate Size |
|---|---|
| app:unoptimized | ~800MB |
| app:multistage | ~10MB |
| app:scratch | ~2MB |
#Task 5: Node.js Optimization (5 min)
bash
1cat << 'EOF' > package.json
2{"name":"test","dependencies":{"express":"^4.18.2"}}
3EOF
4
5cat << 'EOF' > server.js
6const express = require('express');
7const app = express();
8app.get('/', (req, res) => res.send('OK'));
9app.listen(3000);
10EOF
11
12cat << 'EOF' > Dockerfile.node
13FROM node:20-alpine
14WORKDIR /app
15COPY package*.json ./
16RUN npm ci --only=production && npm cache clean --force
17COPY server.js .
18USER node
19EXPOSE 3000
20CMD ["node", "server.js"]
21EOF
22
23docker build -t app:node -f Dockerfile.node .
24docker images app:node#โ Success Criteria
- Unoptimized image built
- Multi-stage build reduces size 90%+
- Scratch image is smallest
- Node.js optimized correctly
#๐งน Cleanup
bash
docker rmi app:unoptimized app:multistage app:scratch app:node 2>/dev/null
cd ~ && rm -rf optimize-lab