docker-best-practices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Best Practices
Docker最佳实践
Multi-Stage Build
多阶段构建
dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine AS runtime
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
COPY /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK CMD wget -qO- http://localhost:3000/healthz || exit 1
CMD ["node", "dist/server.js"]Separate dependency installation from build steps. Final stage contains only runtime artifacts.
dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine AS runtime
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
COPY /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK CMD wget -qO- http://localhost:3000/healthz || exit 1
CMD ["node", "dist/server.js"]将依赖安装与构建步骤分离。最终阶段仅包含运行时产物。
Python Multi-Stage
Python多阶段构建
dockerfile
FROM python:3.12-slim AS builder
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
RUN useradd --create-home appuser
COPY /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY . .
USER appuser
CMD ["gunicorn", "app:create_app()", "-b", "0.0.0.0:8000", "-w", "4"]dockerfile
FROM python:3.12-slim AS builder
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
RUN useradd --create-home appuser
COPY /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY . .
USER appuser
CMD ["gunicorn", "app:create_app()", "-b", "0.0.0.0:8000", "-w", "4"]Docker Compose
Docker Compose配置
yaml
services:
api:
build:
context: .
dockerfile: Dockerfile
target: runtime
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/app
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: app
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d app"]
interval: 5s
timeout: 3s
retries: 5
cache:
image: redis:7-alpine
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
pgdata:yaml
services:
api:
build:
context: .
dockerfile: Dockerfile
target: runtime
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/app
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: app
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d app"]
interval: 5s
timeout: 3s
retries: 5
cache:
image: redis:7-alpine
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
pgdata:.dockerignore
.dockerignore配置
node_modules
.git
.env*
*.md
docker-compose*.yml
.github
coverage
distAlways include a to reduce build context size and prevent leaking secrets.
.dockerignorenode_modules
.git
.env*
*.md
docker-compose*.yml
.github
coverage
dist务必添加文件以减小构建上下文大小,防止泄露敏感信息。
.dockerignoreImage Optimization Tips
镜像优化技巧
bash
undefinedbash
undefinedCheck image size breakdown
查看镜像大小明细
docker history --human --no-trunc <image>
docker history --human --no-trunc <image>
Use dive for layer analysis
使用dive分析镜像层
dive <image>
dive <image>
Multi-arch build
多架构构建
docker buildx build --platform linux/amd64,linux/arm64 -t registry/app:1.0 --push .
Combine `RUN` commands to reduce layers. Order instructions from least to most frequently changing for cache efficiency.docker buildx build --platform linux/amd64,linux/arm64 -t registry/app:1.0 --push .
合并`RUN`命令以减少镜像层数。将指令按从最少变更到最频繁变更的顺序排列,以提高缓存效率。Anti-Patterns
反模式
- Running as root inside containers
- Using when
ADDsuffices (ADD auto-extracts tarballs, pulls URLs)COPY - Storing secrets in environment variables in Dockerfiles
- Not pinning base image versions ()
FROM node:latest - Missing causing large build contexts
.dockerignore - Installing dev dependencies in production images
- 在容器内以root用户运行
- 当足够时使用
COPY(ADD会自动解压tar包、拉取URL)ADD - 在Dockerfile的环境变量中存储敏感信息
- 未固定基础镜像版本(如)
FROM node:latest - 缺少导致构建上下文过大
.dockerignore - 在生产镜像中安装开发依赖
Checklist
检查清单
- Multi-stage build separates build and runtime stages
- Non-root user created and used with directive
USER - Base images pinned to specific versions (e.g., )
node:22-alpine - excludes
.dockerignore,.git,node_modules.env - instruction defined
HEALTHCHECK - Production image contains no build tools or dev dependencies
- uses
docker-composewith health conditionsdepends_on - Secrets passed via build secrets or runtime mounts, not in Dockerfile
ENV
- 多阶段构建分离了构建阶段与运行时阶段
- 创建并使用非root用户(通过指令)
USER - 基础镜像固定到特定版本(例如)
node:22-alpine - 排除了
.dockerignore、.git、node_modules.env - 定义了指令
HEALTHCHECK - 生产镜像不包含构建工具或开发依赖
- 使用带健康检查条件的
docker-composedepends_on - 敏感信息通过构建密钥或运行时挂载传递,而非Dockerfile中的
ENV