BuildKit cache mounts turn npm ci into milliseconds

Enable BuildKit (DOCKER_BUILDKIT=1) and add cache mounts so expensive steps reuse artifacts across builds.

RUN --mount=type=cache,target=/root/.npm \
    npm ci --prefer-offline

Treat cache mounts like shared volumes: never bake secrets into them and periodically invalidate them with --build-arg CACHE_BUST=$(date +%s) when dependencies change.

Secrets stay out of layers with RUN --mount=type=secret

Stop copying .env files into images. BuildKit can inject secrets at build time that never persist in the final layer.

docker build \
  --secret id=npmrc,src=$HOME/.npmrc \
  -t web:secure .
RUN --mount=type=secret,id=npmrc target=/root/.npmrc \
    npm publish

Now your source image remains clean, satisfying both auditors and future you.

4. Compose profiles keep local, staging, and prod in one file

Instead of juggling docker-compose.dev.yml, *-prod.yml, etc., define profiles and start only what each environment needs.

services:
  db:
    image: postgres:16
    profiles: [core]
  mailhog:
    image: mailhog/mailhog
    profiles: [dev]
  worker:
    build: ./worker
    profiles: [core, prod]

Run docker compose --profile core --profile dev up during development and --profile core --profile prod up -d in staging. One file, zero drift.

References: