mcpField
D
docker-best-practices

docker-best-practices

github.com/hieutrtr云与 DevOps888 次安装38 周前更新
代码仓库

关于 docker-best-practices

Docker Best Practices 是面向 Python 后端和 React 前端开发的 Docker 实践指南,涵盖镜像构建、Compose 本地开发、安全加固与镜像扫描。也提供镜像标签策略和故障排查指引。

主要功能

  1. 01多阶段构建与镜像优化
  2. 02Python 和 React 镜像建议
  3. 03Docker Compose 本地开发模式
  4. 04容器安全加固与 Trivy 扫描
  5. 05镜像标签策略

适用场景

  1. 01为 Python 后端编写 Dockerfile
  2. 02缩小镜像并改善构建缓存
  3. 03配置 Compose 本地开发环境
  4. 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.yml
python-dockerfile-template
react-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用于辅助容器

规则:

  1. 切勿使用 latest 标签 —— 始终固定主版本号和次版本号
  2. Python 优先使用 -slim 变体(避免 musl 问题)
  3. Node.js 和 Nginx 优先使用 -alpine 变体(镜像更小)
  4. 每月更新基础镜像,以应用安全补丁
层优化

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"

规则:

  1. 始终使用 git SHA 标记——这是不可变且可追溯的引用
  2. 切勿使用 latest 标记进行部署——始终使用 SHA 标记
  3. 仅在生产环境成功部署后,将 latest 用作便捷别名
  4. 在镜像标签中包含构建元数据
# 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