name: docker-best-practices description: Docker最佳实践包括多阶段构建、compose模式、镜像优化和安全
Docker最佳实践
多阶段构建
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 --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/healthz || exit 1
CMD ["node", "dist/server.js"]
将依赖安装与构建步骤分离。最终阶段只包含运行时代码。
Python多阶段构建
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 --from=builder /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
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
node_modules
.git
.env*
*.md
docker-compose*.yml
.github
coverage
dist
始终包含一个.dockerignore文件以减少构建上下文大小并防止泄露秘密。
镜像优化技巧
# 检查镜像大小分解
docker history --human --no-trunc <image>
# 使用dive进行层分析
dive <image>
# 多架构构建
docker buildx build --platform linux/amd64,linux/arm64 -t registry/app:1.0 --push .
合并RUN命令以减少层。将指令从最不经常更改到最经常更改排序以提高缓存效率。
反模式
- 在容器内以root用户运行
- 当
COPY足够时使用ADD(ADD自动解压tarball,拉取URL) - 在Dockerfile的环境变量中存储秘密
- 未固定基础镜像版本(
FROM node:latest) - 缺少
.dockerignore导致大型构建上下文 - 在生产镜像中安装开发依赖项
检查清单
- [ ] 多阶段构建分离构建和运行阶段
- [ ] 创建非root用户并使用
USER指令 - [ ] 基础镜像固定到特定版本(例如,
node:22-alpine) - [ ]
.dockerignore排除.git、node_modules、.env - [ ] 定义
HEALTHCHECK指令 - [ ] 生产镜像不包含构建工具或开发依赖项
- [ ]
docker-compose使用带有健康条件的depends_on - [ ] 通过构建秘密或运行时挂载传递秘密,而不是在Dockerfile中使用
ENV