Production Docker images: smaller, safer, and faster to build
Docker

Production Docker images: smaller, safer, and faster to build

Nam Nguyen
2 min read
0 views
#docker
#image
#security
#build

Production images need design#

A Dockerfile that works locally may still be poor for production: large images, dev dependencies, copied env files, root users, unclear tags, and slow cache behavior. Treat images as release artifacts.

Multi-stage build#

Build-time tools are often not needed at runtime. Multi-stage builds let you compile in one stage and copy only the required output into a smaller runtime stage.

Dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY --from=build /app/.next ./.next
COPY --from=build /app/public ./public
EXPOSE 3000
CMD ["npm", "run", "start"]

Cache and context#

Copy dependency manifests before source code so install layers can be reused. Keep build context small with .dockerignore to prevent unrelated files from invalidating cache.

Secrets and users#

Never bake secrets into images. Inject database passwords, service keys, signing secrets, and API keys at runtime. Run as a non-root user when the framework and base image allow it.

Checklist#

  • Use explicit base image versions.
  • Use multi-stage builds when runtime needs less than build time.
  • Exclude local output, logs, Git history, and env files.
  • Keep secrets out of images and logs.
  • Tag images by commit SHA or release version.
  • Scan dependencies and images in CI.

Primary references#

Share this article

Help others discover this article

Comments

Loading comments...

Loading comments...

Leave a Comment

Your email will not be published

Minimum 10 characters

0 / 5000