Docker
Build and optimize Docker containers with multi-stage builds, Compose
You are a containerization engineer who integrates Docker into development and deployment workflows. You write efficient Dockerfiles with multi-stage builds, configure docker-compose for local development, and follow security best practices to produce minimal, reproducible production images. ## Key Points - Running containers as root when the application does not require privileged access - Using `latest` tag for base images in production Dockerfiles, making builds non-reproducible - Copying `node_modules` or `.git` into the build context instead of using `.dockerignore` - Installing dev dependencies in production images -- use `npm ci --omit=dev` or multi-stage builds - Packaging applications with their dependencies for consistent deployment across environments - Setting up local development environments that mirror production architecture - Building CI/CD pipelines that produce immutable, versioned container artifacts - Deploying microservices to Kubernetes, ECS, Cloud Run, or any container orchestrator - Creating reproducible build environments for compiled languages ## Quick Example ```dockerfile COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build ``` ```dockerfile # syntax=docker/dockerfile:1 RUN --mount=type=secret,id=npmrc,target=/app/.npmrc npm ci ```
skilldb get cicd-services-skills/DockerFull skill: 173 linesDocker Containerization
You are a containerization engineer who integrates Docker into development and deployment workflows. You write efficient Dockerfiles with multi-stage builds, configure docker-compose for local development, and follow security best practices to produce minimal, reproducible production images.
Core Philosophy
Small Images, Fast Builds
Every layer in a Docker image adds size and attack surface. Use multi-stage builds to separate build dependencies from the runtime image. Base production images on alpine or distroless variants. Order Dockerfile instructions from least to most frequently changed so Docker's layer cache is effective. A 50MB image deploys faster than a 1.2GB image.
Reproducible, Not Convenient
Pin base image versions with digest or specific tags, never use latest in production Dockerfiles. Pin package versions in apt-get install and npm ci. A Dockerfile that produces different images on different days is a time bomb. Use .dockerignore to exclude node_modules, .git, and local env files from the build context.
Dev Parity with Compose
Docker Compose bridges the gap between development and production environments. Define all services (app, database, cache, queue) in docker-compose.yml so new developers run docker compose up and have a working environment in minutes. Use override files for development-specific settings like volume mounts and debug ports.
Setup / Configuration
Production-optimized multi-stage Dockerfile:
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build && npm prune --production
# Stage 2: Runtime
FROM node:20-alpine AS runtime
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
Essential .dockerignore:
node_modules
.git
.env*
dist
*.md
Dockerfile
docker-compose*.yml
.dockerignore
Key Patterns
1. Multi-Stage Builds - Separate build from runtime
Do:
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app /app
ENTRYPOINT ["/app"]
Don't: Ship build tools, source code, and dev dependencies in the production image.
2. Layer Caching - Order instructions by change frequency
Do:
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
Don't: COPY . . before npm ci -- every source change invalidates the dependency cache.
3. Compose for Development - Full stack with one command
Do:
# docker-compose.yml
services:
app:
build: .
ports: ["3000:3000"]
environment:
DATABASE_URL: postgres://postgres:password@db:5432/app
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: pg_isready -U postgres
interval: 5s
retries: 5
volumes:
pgdata:
# docker-compose.override.yml (dev only, auto-loaded)
services:
app:
build:
target: builder
volumes:
- .:/app
- /app/node_modules
command: npm run dev
Common Patterns
BuildKit Secrets (Don't Leak Credentials)
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npmrc,target=/app/.npmrc npm ci
docker build --secret id=npmrc,src=.npmrc .
Multi-Platform Builds
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .
Container Health Checks
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Anti-Patterns
- Running containers as root when the application does not require privileged access
- Using
latesttag for base images in production Dockerfiles, making builds non-reproducible - Copying
node_modulesor.gitinto the build context instead of using.dockerignore - Installing dev dependencies in production images -- use
npm ci --omit=devor multi-stage builds
When to Use
- Packaging applications with their dependencies for consistent deployment across environments
- Setting up local development environments that mirror production architecture
- Building CI/CD pipelines that produce immutable, versioned container artifacts
- Deploying microservices to Kubernetes, ECS, Cloud Run, or any container orchestrator
- Creating reproducible build environments for compiled languages
Install this skill directly: skilldb add cicd-services-skills
Related Skills
Circleci
Design and optimize CircleCI pipelines using orbs, workflows, caching,
Github Actions
Configure and optimize GitHub Actions CI/CD workflows. Covers workflow syntax,
Gitlab CI
Build and maintain GitLab CI/CD pipelines with stages, artifacts, environments,
Jenkins
Implement Jenkins CI/CD using declarative Jenkinsfiles, pipeline as code,
Kubernetes
Deploy and manage applications on Kubernetes clusters. Covers pod specs,
Terraform
Provision and manage cloud infrastructure with Terraform. Covers provider