前置阅读:建议先阅读 Docker 容器化最佳实践。
关键概念:多阶段构建(Multi-Stage Build)允许在单个 Dockerfile 中定义多个 FROM 阶段,前一阶段的编译产物可被复制到后一阶段,最终镜像仅包含运行时所需的最小文件,大幅减少体积和攻击面。
² 多阶段构建原理
# 传统单阶段:最终镜像包含全部编译工具和依赖 FROM golang:1.22 WORKDIR /app COPY . . RUN go build -o server CMD ["./server"] # 结果:1.2GB+ # 多阶段构建:编译与运行完全分离 # === 阶段 1:编译 === FROM golang:1.22-alpine AS builder WORKDIR /build COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server # === 阶段 2:运行 === FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /app COPY --from=builder /build/server . EXPOSE 8080 CMD ["./server"] # 结果:~15MB(缩小 98%)镜像层分析:
层类型 是否进入最终镜像 清理方式 编译依赖层 ❌ 不进入 阶段隔离自动丢弃 源码层 ❌ 不进入 仅复制二进制 编译产物 ✅ 选择性进入 COPY –from 精确提取 运行时基础 ✅ 进入 选择最小基础镜像 ³ 各语言最优 Dockerfile 模板
Go — 最小化标杆:
FROM golang:1.22-alpine AS builder WORKDIR /build # 缓存依赖层 COPY go.mod go.sum ./ RUN go mod download COPY . . # 静态编译:无 CGO,剥离符号表 RUN CGO_ENABLED=0 GOOS=linux go build \ -ldflags="-s -w -extldflags '-static'" \ -a -installsuffix cgo \ -o server # scratch 基础镜像:0 额外开销 FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /build/server /server # 必须暴露端口(scratch 无 shell,无法 debug) EXPOSE 8080 ENTRYPOINT ["/server"] # 结果:通常 < 20MBRust — 静态链接优化:
FROM rust:1.78-slim AS builder WORKDIR /build # 缓存编译依赖 COPY Cargo.toml Cargo.lock ./ RUN mkdir src && echo "fn main() {}" > src/main.rs RUN cargo build --release && rm -rf src COPY . . # musl 静态链接(无需 glibc) RUN rustup target add x86_64-unknown-linux-musl RUN cargo build --release --target x86_64-unknown-linux-musl FROM alpine:latest RUN apk add --no-cache ca-certificates COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/app /app CMD ["/app"]Node.js — pnpm + 精简:
FROM node:20-alpine AS builder WORKDIR /app RUN corepack enable && corepack prepare pnpm@latest --activate COPY pnpm-lock.yaml package.json ./ # 仅安装生产依赖 RUN pnpm install --frozen-lockfile --prod COPY . . RUN pnpm build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production # 复制构建产物和依赖 COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/main.js"]Python — poetry + 多阶段:
FROM python:3.12-slim AS builder WORKDIR /app RUN pip install poetry COPY pyproject.toml poetry.lock ./ # 导出 requirements(不装 poetry 到最终镜像) RUN poetry export -f requirements.txt --without-hashes -o requirements.txt # 构建 wheels RUN pip wheel --no-cache-dir --no-deps --wheel-dir /wheels -r requirements.txt FROM python:3.12-slim WORKDIR /app COPY --from=builder /wheels /wheels RUN pip install --no-cache /wheels/* && rm -rf /wheels COPY . . EXPOSE 8000 CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]⁴ BuildKit 高级特性
# syntax=docker/dockerfile:1.7 FROM node:20-alpine AS deps WORKDIR /app # 缓存挂载:node_modules 跨构建复用 RUN --mount=type=cache,target=/root/.npm \ npm ci # 密钥挂载:安全使用 .env 或私有仓库凭据(不进入镜像层) RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \ npm ci # SSH 挂载:安全克隆私有 git 依赖 RUN --mount=type=ssh \ git clone git@github.com:org/private-repo.git # 绑定挂载:复用宿主机构建缓存 RUN --mount=type=bind,from=builder,source=/build,target=/build \ cp /build/output .启用 BuildKit:
# Docker 23.0+ 默认启用,老版本需设置 export DOCKER_BUILDKIT=1 docker build --secret id=npmrc,src=$HOME/.npmrc . # 远程缓存(CI/CD 场景) docker build \ --cache-from=type=registry,ref=myrepo/cache:build \ --cache-to=type=registry,ref=myrepo/cache:build,mode=max \ -t myapp:latest .⁵ 安全基镜像选型
镜像 大小 包管理器 Shell 适用场景 scratch0 无 无 Go 静态二进制 distroless/static2MB 无 无 通用静态二进制 distroless/cc10MB 无 无 C/C++ 应用 chainguard/static2MB apk 无 Wolfi 包生态系统 alpine5MB apk ash 需要包管理 debian:slim30MB apt bash 兼容性优先 # distroless 示例 FROM golang:1.22 AS builder COPY . . RUN go build -o app FROM gcr.io/distroless/static-debian12:nonroot COPY --from=builder /go/app /app USER nonroot:nonroot ENTRYPOINT ["/app"]⁶ 体积对比基准
同一 Go 应用的不同基础镜像对比:
基础镜像 最终大小 攻击面(CVE) 启动时间 golang:1.221.2GB 高(100+) 2s debian:slim180MB 中(20+) 0.5s alpine25MB 低(5+) 0.3s distroless/static12MB 极低(1-2) 0.2s scratch8MB 几乎为零 0.1s 安全扫描命令:
# Trivy 扫描(推荐) trivy image myapp:latest # Docker Scout(Docker 原生) docker scout cves myapp:latest
延伸阅读:
- Docker 容器化最佳实践 — Dockerfile 编写基础规范
- Docker 生产安全加固 — 运行时安全与镜像加固
- Docker 与 Kubernetes 对比 — 编排层技术选型
← 上一篇
无
下一篇 →
Docker 详解:容器化技术的核心概念与实战入门
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。