mcpField
W
writing-dockerfiles

writing-dockerfiles

github.com/ancoleman云与 DevOps52581 次安装46 周前更新
代码仓库

关于 writing-dockerfiles

这项技能为应用开发者提供生产级 Dockerfile 的编写与优化指导,涵盖多阶段构建、安全加固、缓存和语言专属模式。

主要功能

  1. 01多阶段构建指导
  2. 02按语言选择基础镜像
  3. 03BuildKit 缓存与密钥挂载
  4. 04安全加固与非 root 用户
  5. 05Dockerfile 校验与镜像分析

适用场景

  1. 01为应用编写生产级 Dockerfile
  2. 02用多阶段构建缩小镜像
  3. 03避免凭据留在镜像层中
  4. 04应用语言专属容器模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ancoleman/ai-design-components --skill writing-dockerfiles

安装后在 Claude Code 中输入/writing-dockerfiles确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

outputs.yaml
examples/
go-microservice.Dockerfile
nodejs-express.Dockerfile
python-fastapi.Dockerfile
rust-actix.Dockerfile
references/
base-image-selection.md
buildkit-features.md
go-dockerfiles.md
java-dockerfiles.md
nodejs-dockerfiles.md
python-dockerfiles.md
rust-dockerfiles.md
security-hardening.md
scripts/
analyze_image_size.sh
validate_dockerfile.py

详细介绍

编写 Dockerfile

编写适用于生产环境的 Dockerfile,采用多阶段构建、安全加固和针对语言的优化。

何时使用此技能

在以下情况调用:

  • “为 [Python/Node.js/Go/Rust] 应用编写 Dockerfile”
  • “优化此 Dockerfile 以减小镜像体积”
  • “为……使用多阶段构建”
  • “通过非 root 用户加固 Dockerfile 安全性”
  • “使用 distroless 基础镜像”
  • “添加 BuildKit 缓存挂载”
  • “防止机密泄漏到 Docker 层中”

快速决策框架

回答以下三个问题,以确定采用哪种方案:

1. 使用哪种语言?

  • Python → 参见 references/python-dockerfiles.md
  • Node.js → 参见 references/nodejs-dockerfiles.md
  • Go → 参见 references/go-dockerfiles.md
  • Rust → 参见 references/rust-dockerfiles.md
  • Java → 参见 references/java-dockerfiles.md

2. 安全性是否至关重要?

  • 是 → 使用 distroless 运行时镜像(参见 references/security-hardening.md)
  • 否 → 使用 slim/alpine 基础镜像

3. 镜像体积是否至关重要?

  • 是(<50MB)→ 多阶段构建 + distroless + 静态链接
  • 否(<500MB)→ 多阶段构建 + slim 基础镜像

核心概念

多阶段构建

将构建环境与运行时环境分离,以尽可能减小最终镜像体积。

模式:

# Stage 1: Build
FROM build-image AS builder
RUN compile application

# Stage 2: Runtime
FROM minimal-runtime-image
COPY --from=builder /app/binary /app/
CMD ["/app/binary"]

优势:

  • 镜像体积缩小 80-95%(不包括构建工具)
  • 提升安全性(生产环境中不包含编译器)
  • 部署更快
  • 更好地利用层缓存
基础镜像选择

决策矩阵:

语言构建阶段运行时阶段最终体积
Go(静态)golang:1.22-alpinegcr.io/distroless/static-debian1210-30MB
Rust(静态)rust:1.75-alpinescratch5-15MB
Pythonpython:3.12-slimpython:3.12-slim200-400MB
Node.jsnode:20-alpinenode:20-alpine150-300MB
Javamaven:3.9-eclipse-temurin-21eclipse-temurin:21-jre-alpine200-350MB

Distroless 镜像(由 Google 维护):

  • gcr.io/distroless/static-debian12 → 静态二进制文件(2MB)
  • gcr.io/distroless/base-debian12 → 使用 libc 的动态二进制文件(20MB)
  • gcr.io/distroless/python3-debian12 → Python 运行时(60MB)
  • gcr.io/distroless/nodejs20-debian12 → Node.js 运行时(150MB)

完整比较请参见 references/base-image-selection.md。

BuildKit 功能

启用 BuildKit,以使用高级缓存和安全功能:

export DOCKER_BUILDKIT=1
docker build .
# OR
docker buildx build .

主要功能:

  • --mount=type=cache → 持久化包管理器缓存
  • --mount=type=secret → 注入机密,而不将其存储在各层中
  • --mount=type=ssh → 转发 SSH Agent,以访问私有仓库
  • 并行执行各阶段
  • 改进层缓存

详细模式请参见 references/buildkit-features.md。

层优化

按变化频率从低到高排列 Dockerfile 指令:

# 1. Base image (rarely changes)
FROM python:3.12-slim

# 2. System packages (rarely changes)
RUN apt-get update && apt-get install -y build-essential

# 3. Dependencies manifest (changes occasionally)
COPY requirements.txt .
RUN pip install -r requirements.txt

# 4. Application code (changes frequently)
COPY . .

# 5. Runtime configuration (rarely changes)
CMD ["python", "app.py"]

BuildKit 缓存挂载:

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

缓存会在各次构建之间保留,从而避免重复下载。

安全加固

基本安全实践:

1. 非 root 用户

# Debian/Ubuntu
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Alpine
RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Distroless (built-in)
USER nonroot:nonroot

2. 机密管理

# ❌ NEVER: Secret in layer history
RUN git clone https://${GITHUB_TOKEN}@github.com/private/repo.git

# ✅ ALWAYS: BuildKit secret mount
RUN --mount=type=secret,id=github_token \
    TOKEN=$(cat /run/secrets/github_token) && \
    git clone https://${TOKEN}@github.com/private/repo.git

使用以下命令构建:

docker buildx build --secret id=github_token,src=./token.txt .

3. 漏洞扫描

# Trivy (recommended)
trivy image myimage:latest

# Docker Scout
docker scout cves myimage:latest

4. 健康检查

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

全面的安全加固模式请参见 references/security-hardening.md。

.dockerignore 配置

创建 .dockerignore,以排除不必要的文件:

# Version control
.git
.gitignore

# CI/CD
.github
.gitlab-ci.yml

# IDE
.vscode
.idea

# Testing
tests/
coverage/
**/*_test.go
**/*.test.js

# Build artifacts
node_modules/
dist/
build/
target/
__pycache__/

# Environment
.env
.env.local
*.log

这样可以缩小构建上下文,并防止机密泄漏。

特定语言的模式

Python 快速参考

三种方案:

  1. pip(简单) → 单阶段构建,使用 requirements.txt
  2. poetry(生产环境) → 多阶段构建,使用虚拟环境
  3. uv(最快) → 速度比 pip 快 10-100 倍

示例:Poetry 多阶段构建

FROM python:3.12-slim AS builder
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install poetry==1.7.1

COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt

RUN --mount=type=cache,target=/root/.cache/pip \
    python -m venv /opt/venv && \
    /opt/venv/bin/pip install -r requirements.txt

FROM python:3.12-slim
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
USER 1000:1000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]

完整模式请参见 references/python-dockerfiles.md 和 examples/python-fastapi.Dockerfile。

Node.js 快速参考

关键模式:

  • 使用 npm ci(而不是 npm install)进行可复现构建
  • 多阶段:构建阶段 → 仅保留生产依赖
  • 内置 node 用户(UID 1000)
  • Alpine 变体体积最小(约 180MB,而非 1GB)

示例:Express 多阶段构建

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build
RUN npm prune --omit=dev

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/index.js"]

请参阅 references/nodejs-dockerfiles.md,了解 npm/pnpm/yarn 模式,以及 examples/nodejs-express.Dockerfile。

Go 快速参考

尽可能精简的镜像:

  • 静态二进制文件(CGO_ENABLED=0)+ distroless = 10-30MB
  • 使用 -ldflags="-s -w" 剥离符号
  • 同时缓存 /go/pkg/mod 和构建缓存

示例:Distroless 静态镜像

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main .

FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/main /app/main
USER nonroot:nonroot
ENTRYPOINT ["/app/main"]

请参阅 references/go-dockerfiles.md 和 examples/go-microservice.Dockerfile。

Rust 快速参考

超小型静态二进制文件:

  • musl 静态链接 → 无 libc 依赖
  • scratch 基础镜像(额外开销为 0 字节)
  • 最终镜像:5-15MB

示例:Scratch 基础镜像

FROM rust:1.75-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app

# Cache dependencies
COPY Cargo.toml Cargo.lock ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    mkdir src && echo "fn main() {}" > src/main.rs && \
    cargo build --release --target x86_64-unknown-linux-musl && \
    rm -rf src

# Build application
COPY src ./src
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    cargo build --release --target x86_64-unknown-linux-musl

FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/app /app
USER 1000:1000
ENTRYPOINT ["/app"]

请参阅 references/rust-dockerfiles.md 和 examples/rust-actix.Dockerfile。

包管理器缓存挂载

BuildKit 缓存挂载位置:

语言包管理器缓存挂载目标
Pythonpip--mount=type=cache,target=/root/.cache/pip
Pythonpoetry--mount=type=cache,target=/root/.cache/pypoetry
Pythonuv--mount=type=cache,target=/root/.cache/uv
Node.jsnpm--mount=type=cache,target=/root/.npm
Node.jspnpm--mount=type=cache,target=/root/.local/share/pnpm/store
Gogo mod--mount=type=cache,target=/go/pkg/mod
Rustcargo--mount=type=cache,target=/usr/local/cargo/registry

持久化缓存可避免在不同构建中重复下载包。

验证与测试

验证 Dockerfile 质量:

# Lint Dockerfile
python scripts/validate_dockerfile.py Dockerfile

# Scan for vulnerabilities
trivy image myimage:latest

# Analyze image size
docker images myimage:latest
docker history myimage:latest

比较优化结果:

# Before optimization
docker build -t myapp:before .

# After optimization
docker build -t myapp:after .

# Compare
bash scripts/analyze_image_size.sh myapp:before myapp:after

请参阅 scripts/validate_dockerfile.py,了解自动化 Dockerfile 检查。

与相关技能集成

上游(提供输入):

  • testing-strategies → 在容器化之前测试应用程序
  • security-hardening → 在 Docker 层之前加固应用程序安全性

下游(使用 Dockerfile):

  • building-ci-pipelines → 在 CI 中构建并推送 Docker 镜像
  • kubernetes-operations → 将容器部署到 K8s 集群
  • infrastructure-as-code → 使用 Terraform/Pulumi 部署容器

并行(相关上下文):

  • secret-management → 注入运行时密钥(K8s 密钥、密钥库)
  • observability → 收集容器日志和指标

常见模式快速参考

1. 静态二进制文件(Go/Rust)→ 最小镜像

  • 构建:特定语言的构建器镜像
  • 运行时:gcr.io/distroless/static-debian12 或 scratch
  • 体积:5-30MB

2. 解释型语言(Python/Node.js)→ 针对生产环境优化

  • 构建:安装依赖、构建产物
  • 运行时:相同基础镜像,仅保留生产依赖
  • 体积:150-400MB

3. JVM(Java)→ 优化运行时

  • 构建:使用完整 JDK 的 Maven/Gradle
  • 运行时:仅包含 JRE 的镜像(alpine 变体)
  • 体积:200-350MB

4. 安全关键型场景 → 最大限度加固

  • 基础镜像:Distroless 镜像
  • 用户:非 root 用户(nonroot:nonroot)
  • 密钥:BuildKit 密钥挂载
  • 扫描:在 CI 中使用 Trivy/Docker Scout

5. 开发 → 快速迭代

  • 基础镜像:完整语言镜像(而非 slim)
  • 卷:挂载源代码
  • 热重载:特定语言的工具
  • 本技能不涵盖此内容(请参阅 Docker Compose 文档)

应避免的反模式

❌ 绝不:

  • 使用 latest 标签(会导致构建结果不可预测)
  • 在生产环境中以 root 身份运行
  • 在 ENV 变量或镜像层中存储密钥
  • 安装不必要的软件包
  • 合并无关的 RUN 命令(会破坏缓存)
  • 跳过 .dockerignore(导致构建上下文臃肿)

✅ 始终:

  • 固定精确的镜像版本(使用 python:3.12.1-slim,而非 python:3)
  • 创建并使用非 root 用户
  • 使用 BuildKit 密钥挂载存储凭据
  • 尽量减少镜像层和镜像体积
  • 按照从最少变更到最频繁变更的顺序排列命令
  • 创建 .dockerignore 文件

其他资源

基础镜像仓库:

  • Google Distroless:gcr.io/distroless/*
  • Docker Hub 官方镜像:python:*、node:*、golang:*
  • Red Hat UBI:registry.access.redhat.com/ubi9/*

漏洞扫描器:

  • Trivy(推荐):trivy image myimage:latest
  • Docker Scout:docker scout cves myimage:latest
  • Grype:grype myimage:latest

参考文档:

  • references/base-image-selection.md → 完整的基础镜像对比
  • references/buildkit-features.md → 高级 BuildKit 模式
  • references/security-hardening.md → 全面的安全指南
  • references/ 目录中的语言专属参考文档
  • examples/ 目录中的可运行示例

评论

支持 Markdown