Docker Multi-Stage Builds in CI/CD Pipelines
Shrink images, speed up pipelines, and improve security with multi-stage Dockerfiles in GitLab CI.
Fat container images slow pulls, widen attack surface, and waste registry storage. Multi-stage builds separate build dependencies from runtime artifacts.
Build Pipeline Flow
Multi-Stage Dockerfile
# Stage 1: install dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package-lock.json package.json ./
RUN npm ci
# Stage 2: build application
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 3: minimal runtime
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]BuildKit cache
Enable BuildKit and cache mounts in CI to avoid re-downloading dependencies on every pipeline run.
GitLab CI with BuildKit
variables:
DOCKER_BUILDKIT: "1"
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build
--cache-from $CI_REGISTRY_IMAGE:latest
--tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $CI_REGISTRY_IMAGE:latest
.
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latestImage Size Comparison
Security Benefits
- No compiler or dev tools in production image
- Smaller surface for CVE scanners to flag
- Non-root user in final stage
- Distroless or Alpine for minimal OS packages
Conclusion
Multi-stage builds belong in every serious CI/CD pipeline. The upfront Dockerfile complexity pays off in faster deploys and safer production containers.
Related Articles
GitLab CI Best Practices for Microservices
Patterns and practices for building efficient, secure CI/CD pipelines in GitLab for microservice architectures.
Trunk-Based Development with Modern CI/CD
Ship faster with short-lived branches, feature flags, and continuous integration on the main trunk.
Vercel + GitLab: CI/CD for Next.js Portfolios
Combine GitLab for source control and optional CI checks with Vercel for zero-config Next.js deployment.