You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
One of Docker's most powerful features for production images is multi-stage builds. They let you use multiple FROM instructions in a single Dockerfile, where each FROM starts a new build stage. You can selectively copy artifacts from one stage to another, leaving behind everything that was only needed to build the application — compilers, test tools, build caches — so your final image contains only what is needed to run.
Without multi-stage builds, a typical compiled application Dockerfile might look like this:
# Single-stage: everything ends up in the final image
FROM golang:1.22
WORKDIR /app
COPY . .
RUN go build -o server .
CMD ["./server"]
This works but the final image contains the entire Go toolchain (several hundred megabytes) even though the running application only needs the compiled binary (a few megabytes).
# Stage 1: builder — installs tools and compiles the code
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server .
# Stage 2: final — only the binary, on a minimal base
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
The COPY --from=builder instruction copies the compiled binary from the builder stage into the alpine stage. The Go toolchain never makes it into the final image.
# Stage 1: install dependencies and build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: production runtime
FROM node:20-alpine AS runner
ENV NODE_ENV=production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json .
EXPOSE 3000
CMD ["node", "dist/index.js"]
You can build only up to a specific stage with the --target flag. This is useful for running tests or for local development builds:
# Build only the builder stage (e.g., to run tests in CI)
docker build --target builder -t my-app:test .
# Run tests inside the builder stage
docker run --rm my-app:test npm test
# Build the full production image
docker build -t my-app:prod .
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.