关于 docker-best-practices
Docker Best Practices 是面向 Python 后端和 React 前端开发的 Docker 实践指南,涵盖镜像构建、Compose 本地开发、安全加固与镜像扫描。也提供镜像标签策略和故障排查指引。
主要功能
- 01多阶段构建与镜像优化
- 02Python 和 React 镜像建议
- 03Docker Compose 本地开发模式
- 04容器安全加固与 Trivy 扫描
- 05镜像标签策略
适用场景
- 01为 Python 后端编写 Dockerfile
- 02缩小镜像并改善构建缓存
- 03配置 Compose 本地开发环境
- 04扫描镜像漏洞并规划标签
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ hieutrtr/ ai1-skills --skill docker-best-practices安装后在 Claude Code 中输入/docker-best-practices确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/docker-compose-template.ymlpython-dockerfile-templatereact-dockerfile-template详细介绍
Docker 最佳实践
适用场景
在以下情况下启用此技能:
- 为 Python 后端或 React 前端创建新的 Dockerfile
- 优化现有 Docker 镜像,以减小体积或加快构建速度
- 为本地开发设置 Docker Compose
- 配置多阶段构建,以分离构建依赖项和运行时依赖项
- 强化容器安全性(非 root 用户、精简基础镜像)
- 使用 Trivy 扫描 Docker 镜像的安全性
- 为 CI/CD 流水线设计镜像标签策略
- 排查 Docker 构建失败或运行时问题
请勿将此技能用于:
- 部署编排或 CI/CD 流水线(使用
deployment-pipeline) - Kubernetes 配置或 Helm 图表
- 云基础设施配置(Terraform、CloudFormation)
- 应用代码模式(使用
python-backend-expert或react-frontend-expert)
说明
多阶段构建策略
多阶段构建通过分离构建时和运行时依赖项来保持最终镜像精简。
原则: 在完整镜像中构建,在精简镜像中运行。只复制运行时所需内容。
┌──────────────────────────────────┐
│ Stage 1: Builder │
│ Full SDK, build tools, deps │
│ Compile, install, build │
├──────────────────────────────────┤
│ Stage 2: Runtime │
│ Minimal base image │
│ COPY --from=builder artifacts │
│ Non-root user, health check │
└──────────────────────────────────┘
Python 后端 Dockerfile
完整模板请参阅 references/python-dockerfile-template。
Python 的关键决策:
# Stage 1: Build dependencies
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Stage 2: Runtime
FROM python:3.12-slim AS runtime
# Install only runtime system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 curl \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN groupadd -r appuser && useradd -r -g appuser -d /app -s /sbin/nologin appuser
WORKDIR /app
COPY --from=builder /install /usr/local
COPY src/ ./src/
COPY alembic/ ./alembic/
COPY alembic.ini .
RUN chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
选择这些方案的原因:
- 使用
python:3.12-slim而不是alpine—— 避免二进制 wheel 的 musl 兼容性问题 --no-cache-dir—— 防止 pip 缓存使镜像变得臃肿--prefix=/install—— 隔离已安装的软件包,以便干净地执行 COPY- 运行时使用
libpq5,仅在构建时使用libpq-dev—— 尽量减少运行时依赖项 - 运行时使用
curl—— HEALTHCHECK 命令需要它
React 前端 Dockerfile
完整模板请参阅 references/react-dockerfile-template。
React 的关键决策:
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
# Stage 2: Serve with Nginx
FROM nginx:alpine AS runtime
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup && \
chown -R appuser:appgroup /var/cache/nginx /var/log/nginx /etc/nginx/conf.d && \
touch /var/run/nginx.pid && chown appuser:appgroup /var/run/nginx.pid
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -q --spider http://localhost:8080/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
选择这些方案的原因:
- 构建时使用
node:20-alpine—— 体积最小的 Node 镜像,仅在构建时需要 - 使用
nginx:alpine提供服务 —— 基础镜像约 7MB,是适用于生产环境的静态文件服务器 npm ci—— 根据锁定文件确定性地安装,比npm install更快--ignore-scripts—— 安全措施,可防止安装期间运行任意脚本- 最终镜像不包含 Node.js 运行时 —— 仅包含静态文件和 Nginx
基础镜像选择指南
| 用例 | 基础镜像 | 大小 | 说明 |
|---|---|---|---|
| Python 后端 | python:3.12-slim | ~150MB | 与二进制 wheel 的兼容性最佳 |
| Python 后端(精简版) | python:3.12-alpine | ~50MB | 某些软件包可能需要针对 musl 进行适配 |
| React 构建阶段 | node:20-alpine | ~130MB | 仅在构建期间使用 |
| React 运行时 | nginx:alpine | ~7MB | 用于生产环境的静态文件服务 |
| 实用工具/脚本 | alpine:3.19 | ~5MB | 用于辅助容器 |
规则:
- 切勿使用
latest标签 —— 始终固定主版本号和次版本号 - Python 优先使用
-slim变体(避免 musl 问题) - Node.js 和 Nginx 优先使用
-alpine变体(镜像更小) - 每月更新基础镜像,以应用安全补丁
层优化
Docker 会缓存层。按照从最少变化到最多变化的顺序排列指令。
最佳层顺序:
# 1. Base image (changes rarely)
FROM python:3.12-slim
# 2. System dependencies (changes monthly)
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 curl && rm -rf /var/lib/apt/lists/*
# 3. Create user (changes never)
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 4. Python dependencies (changes weekly)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 5. Application code (changes every commit)
COPY src/ ./src/
# 6. Runtime config (changes rarely)
USER appuser
EXPOSE 8000
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
应避免的常见错误:
# BAD: Copying everything before installing dependencies (busts cache)
COPY . .
RUN pip install -r requirements.txt
# GOOD: Copy only requirements first, then install, then copy code
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src/
减少层数:
# BAD: Multiple RUN commands create multiple layers
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# GOOD: Single RUN command, single layer, clean up in same layer
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
.dockerignore
始终添加 .dockerignore,以防止不必要的文件进入构建上下文。
# Version control
.git
.gitignore
# Python
__pycache__
*.pyc
*.pyo
.pytest_cache
.mypy_cache
.ruff_cache
*.egg-info
dist/
build/
.venv/
venv/
# Node
node_modules/
npm-debug.log*
.next/
coverage/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Docker
Dockerfile*
docker-compose*
.dockerignore
# Environment files
.env
.env.*
!.env.example
# Documentation
*.md
docs/
LICENSE
# CI/CD
.github/
.gitlab-ci.yml
# OS
.DS_Store
Thumbs.db
.dockerignore 的影响:
- 不使用时:构建上下文可能达到 500MB 以上(node_modules、.git)
- 使用后:构建上下文通常为 5-20MB
- 构建速度更快,也不会有从
.env文件泄漏密钥的风险
安全强化
非 Root 用户
生产环境中切勿以 root 身份运行容器。
# Create a dedicated user with no shell and no home directory
RUN groupadd -r appuser && \
useradd -r -g appuser -d /app -s /sbin/nologin appuser
# Set ownership of application files
COPY --chown=appuser:appuser src/ ./src/
# Switch to non-root user
USER appuser
使用 Trivy 进行安全扫描
部署前扫描镜像中的漏洞。
# Install Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
# Scan image for vulnerabilities
trivy image --severity HIGH,CRITICAL app-backend:latest
# Scan and fail if HIGH/CRITICAL vulnerabilities found
trivy image --exit-code 1 --severity HIGH,CRITICAL app-backend:latest
# Generate JSON report
trivy image --format json --output trivy-report.json app-backend:latest
# Scan Dockerfile for misconfigurations
trivy config Dockerfile
集成到 CI/CD:
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'app-backend:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
其他安全措施
# Read-only filesystem where possible
# (set at runtime with docker run --read-only)
# No new privileges
# (set at runtime with docker run --security-opt=no-new-privileges)
# Drop all capabilities, add only what is needed
# (set at runtime with docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE)
# Use COPY instead of ADD (ADD can auto-extract tarballs, security risk)
COPY requirements.txt . # GOOD
# ADD requirements.txt . # AVOID unless you need tar extraction
本地开发的 Docker Compose
完整模板请参阅 references/docker-compose-template.yml。
架构:
┌────────────┐ ┌────────────┐
│ Frontend │ │ Backend │
│ React:3000 │───>│ FastAPI:8000│
└────────────┘ └─────┬──────┘
│
┌──────┴──────┐
│ │
┌────┴────┐ ┌────┴────┐
│PostgreSQL│ │ Redis │
│ :5432 │ │ :6379 │
└─────────┘ └─────────┘
用于开发的 Compose 关键功能:
services:
backend:
build:
context: .
dockerfile: Dockerfile.backend
target: builder # Use builder stage for development (has dev tools)
volumes:
- ./src:/app/src # Hot reload
environment:
- DEBUG=true
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/app_dev
depends_on:
db:
condition: service_healthy
ports:
- "8000:8000"
frontend:
build:
context: ./frontend
target: builder
volumes:
- ./frontend/src:/app/src # Hot reload
ports:
- "3000:3000"
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
volumes:
pgdata:
基本 Compose 模式:
- 使用
depends_on和condition: service_healthy控制启动顺序 - 将源代码挂载为卷,以便在开发过程中热重载
- 使用命名卷持久化数据库数据
- 设置
target: builder,使用包含开发依赖项的构建阶段 - 为所有基础设施服务定义健康检查
镜像标记策略
在所有环境中使用一致的标记策略。
标记格式:
registry.example.com/app-backend:<tag>
标记规则:
| 标记 | 适用时机 | 示例 | 用途 |
|---|---|---|---|
git-<sha> | 每次构建 | git-a1b2c3d | 对应确切代码的不可变引用 |
branch-<name> | 每次推送 | branch-main | 分支的最新版本(可变) |
v<semver> | 发布时 | v1.2.3 | 语义化版本发布 |
latest | 生产环境部署时 | latest | 当前生产版本(可变) |
staging | 预发布环境部署时 | staging | 当前预发布版本(可变) |
实现:
# Build with git SHA tag (immutable)
GIT_SHA=$(git rev-parse --short HEAD)
docker build -t "app-backend:git-${GIT_SHA}" .
# Tag for the branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)
docker tag "app-backend:git-${GIT_SHA}" "app-backend:branch-${BRANCH}"
# Tag for release
docker tag "app-backend:git-${GIT_SHA}" "app-backend:v1.2.3"
# Tag as latest for production
docker tag "app-backend:git-${GIT_SHA}" "app-backend:latest"
规则:
- 始终使用 git SHA 标记——这是不可变且可追溯的引用
- 切勿使用
latest标记进行部署——始终使用 SHA 标记 - 仅在生产环境成功部署后,将
latest用作便捷别名 - 在镜像标签中包含构建元数据
# Add metadata labels
LABEL org.opencontainers.image.source="https://github.com/org/repo"
LABEL org.opencontainers.image.revision="${GIT_SHA}"
LABEL org.opencontainers.image.created="${BUILD_DATE}"
快速参考
# Build images
docker build -t app-backend:$(git rev-parse --short HEAD) -f Dockerfile.backend .
docker build -t app-frontend:$(git rev-parse --short HEAD) -f Dockerfile.frontend .
# Start local development
docker compose up -d && docker compose logs -f backend
# Scan for vulnerabilities
trivy image --severity HIGH,CRITICAL app-backend:latest
# Check image sizes
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep app-
# Clean up
docker image prune -f
评论
支持 Markdown