How to Optimize Docker for Production: Best Practices
To optimize
Docker for production, use multi-stage builds to reduce image size, run containers as a non-root user, and minimize layers by combining commands. Also, use a .dockerignore file to exclude unnecessary files and keep images secure and efficient.Syntax
The basic syntax for a Dockerfile optimized for production includes using FROM for base images, RUN to install dependencies, COPY to add files, and USER to switch to a non-root user. Multi-stage builds use multiple FROM statements to separate build and runtime environments.
dockerfile
FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . FROM node:18-alpine WORKDIR /app COPY --from=build /app . USER node CMD ["node", "server.js"]
Example
This example shows a multi-stage Dockerfile for a Node.js app that installs only production dependencies, copies only necessary files, and runs as a non-root user to improve security and reduce image size.
dockerfile
FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . FROM node:18-alpine WORKDIR /app COPY --from=build /app . USER node CMD ["node", "server.js"]
Common Pitfalls
Common mistakes include using large base images like ubuntu unnecessarily, running containers as root, and copying unnecessary files which increase image size. Forgetting to use .dockerignore can also bloat images.
dockerfile
### Wrong way (large image, root user, no .dockerignore) FROM ubuntu:20.04 WORKDIR /app COPY . . RUN apt-get update && apt-get install -y nodejs npm RUN npm install CMD ["node", "server.js"] ### Right way (smaller image, non-root user, .dockerignore used) FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . FROM node:18-alpine WORKDIR /app COPY --from=build /app . USER node CMD ["node", "server.js"]
Quick Reference
- Use
multi-stage buildsto keep images small. - Choose minimal base images like
alpine. - Run containers as a
non-root userfor security. - Use
.dockerignoreto exclude unnecessary files. - Combine
RUNcommands to reduce layers.
Key Takeaways
Use multi-stage builds to separate build and runtime environments and reduce image size.
Run containers as a non-root user to improve security.
Use minimal base images like alpine to keep images lightweight.
Add a .dockerignore file to exclude unnecessary files from the image.
Combine RUN commands to minimize image layers and improve build speed.