PABCD Initiative Documentation Hub pabcd_initiative codexclaw cli-jaw

Docker — Container Build & Security Patterns

Source: dev-devops/references/docker.md

Docker — Container Build & Security Patterns

Last reviewed: 2026-07-02

Applies to: Docker 27+, BuildKit, OCI images

When to read: Container build/deploy tasks

Canonical owner: dev-devops §1

Cross-ref: read platform-engineering.md for provider routing and release

capability framing; read package-release.md for package-registry auth; read

../../dev-security/references/supply-chain-sbom.md for SBOM/signing depth.

---

§1 Multi-Stage Build Templates

Node.js (Bun)

# syntax=docker/dockerfile:1
FROM oven/bun:1.2 AS build
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build

FROM gcr.io/distroless/nodejs22-debian12
COPY --from=build /app/dist /app
USER nonroot:nonroot
CMD ["app/server.js"]

Node.js (npm)

FROM node:22-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build

FROM gcr.io/distroless/nodejs22-debian12
COPY --from=build /app/dist /app
USER nonroot:nonroot
CMD ["app/server.js"]

Python

FROM python:3.13-slim AS build
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN pip install uv && uv sync --frozen
COPY . .

FROM python:3.13-slim
WORKDIR /app
COPY --from=build /app/.venv /app/.venv
COPY --from=build /app /app
ENV PATH="/app/.venv/bin:$PATH"
RUN adduser --system --no-create-home app
USER app
CMD ["python", "-m", "app"]

Go

FROM golang:1.25 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app .

FROM gcr.io/distroless/static-debian12
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

---

§2 Docker Compose Development Patterns

services:
  app:
    build: .
    ports: ["3000:3000"]
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      db: { condition: service_healthy }
      redis: { condition: service_healthy }
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/app_dev

  db:
    image: postgres:17
    volumes: [pgdata:/var/lib/postgresql/data]
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app_dev
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "app"]
      interval: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      retries: 5

volumes:
  pgdata:
RuleDetail
Health conditionsdepends_on: { condition: service_healthy } — never bare depends_on
VolumesBind mount for source, named volume for DB data
Networksinternal for DB, default for app (optional explicit separation)

---

§3 Image Optimization

Base Image Selection Tree

Binary TypeBase ImageSize
Static binary (Go, Rust)scratch or distroless/static~2MB
Node.jsdistroless/nodejs22-debian12~130MB
Pythonpython:3.13-slim~150MB
General C/C++distroless/cc-debian12~20MB

.dockerignore Required Entries

.git
node_modules
dist/
coverage/
.env*
*.log
__pycache__/
.pytest_cache/
.mypy_cache/
*.pyc
.DS_Store
docker-compose*.yml
Dockerfile*
README*

Layer Caching Order

  1. Copy dependency manifests (package.json, go.mod, pyproject.toml)
  2. Install dependencies (cached unless manifests change)
  3. Copy source code
  4. Build

---

§4 Security Scanning CI Pipeline

Trivy

# Scan image — fail on CRITICAL/HIGH
trivy image --severity CRITICAL,HIGH --exit-code 1 myapp:sha-123

# Generate SBOM
trivy image --format spdx-json --output sbom.spdx.json myapp:sha-123

# Scan with VEX filter (suppress known false positives)
trivy image --vex policy.vex.json myapp:sha-123

Docker Scout

docker scout cves myapp:sha-123 --exit-code --only-severity critical,high
docker scout recommendations myapp:sha-123

SBOM + Signing

# Generate SBOM with Syft
syft myapp:sha-123 -o spdx-json > sbom.spdx.json

# Sign image with Cosign
cosign sign --key cosign.key myapp@sha256:abc123...

# Attest SBOM
cosign attest --predicate sbom.spdx.json --type spdxjson myapp@sha256:abc123...

# Verify
cosign verify --key cosign.pub myapp@sha256:abc123...

---

§5 BuildKit Secrets

BuildKit secrets are for private dependency install during image builds. Do

not reuse this pattern as the default for public package publishing. For npm,

PyPI, Bun-to-npm, Homebrew, and registry publish decisions, read

references/package-release.md first.

# Mount secret at build time — never exposed in image layers
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm install

Build command:

docker build --secret id=npm_token,src=.npmrc .
BannedFix
ARG NPM_TOKEN=xxx--mount=type=secret
COPY .env .Inject at runtime via env vars
ENV SECRET=xxx in DockerfileRuntime --env or secrets mount

---

§6 Anti-Patterns (Detailed)

BannedWhyFix
FROM node:latestIrreproducible; breaks on major updatesPin: node:22-slim@sha256:...
USER root in final imageFull host-equivalent privileges if container escapesUSER nonroot:nonroot or dedicated user
COPY . . before dependency installEvery source change invalidates dependency cacheCopy manifests first, install, then copy source
apt-get install without cleanup100MB+ wasted on package cache--no-install-recommends && rm -rf /var/lib/apt/lists/*
No image scan in CIShip known CVEs to productionTrivy/Scout gate with --exit-code 1
docker push without signingNo supply chain verificationCosign sign + attest
Multi-purpose single stageBuild tools in production imageMulti-stage: build → runtime

Sources (supply-chain baseline, checked 2026-07-02)

ClaimSource Distroless active, Debian-based, Cosign keyless-signedhttps://github.com/GoogleContainerTools/distroless
Chainguard/Wolfi production option (rebuilds, SBOM, SLAs)https://edu.chainguard.dev/chainguard/chainguard-images/overview/
Trivy v0.72.0 (2026-06-30)https://github.com/aquasecurity/trivy/releases
Docker Scout SBOM-based matchinghttps://docs.docker.com/scout/
Syft/Grype/Cosign activehttps://github.com/anchore/syft/releases ; https://github.com/anchore/grype/releases ; https://github.com/sigstore/cosign/releases
DORA 2025: AI as amplifierhttps://dora.dev/research/