docker-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Docker Development

Docker 开发

Patterns for building, testing, and deploying Docker containers.
构建、测试和部署Docker容器的模式。

Core Principles

核心原则

  1. Minimal images -- Alpine/distroless, multi-stage builds
  2. Security first -- Non-root USER, no secrets in layers, pin versions
  3. Testable -- Verifiable in CI with entrypoint bypass and DNS mocking
  4. Cache-efficient -- Copy dependency files first, clean in same layer
  1. 最小化镜像 -- 使用Alpine/distroless基础镜像、多阶段构建
  2. 安全优先 -- 使用非root用户USER、不在镜像层中存储密钥、固定版本
  3. 可测试性 -- 在CI中通过绕过入口点和DNS模拟进行验证
  4. 缓存高效 -- 先复制依赖文件,在同一层中清理无用内容

Quick Reference

快速参考

Multi-Stage Build (Node.js)

多阶段构建(Node.js)

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

FROM node:20-alpine
RUN addgroup -g 1001 app && adduser -u 1001 -G app -D app
USER app
COPY --from=builder /app .
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "server.js"]
dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

FROM node:20-alpine
RUN addgroup -g 1001 app && adduser -u 1001 -G app -D app
USER app
COPY --from=builder /app .
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "server.js"]

Multi-Stage Build (Go -- scratch/distroless)

多阶段构建(Go -- scratch/distroless)

dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .

FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/server /server
CMD ["/server"]
dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .

FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/server /server
CMD ["/server"]

Layer Optimization

镜像层优化

dockerfile
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/*
dockerfile
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/*

Build Cache: Copy Dependency Files First

构建缓存:先复制依赖文件

dockerfile
COPY package*.json ./
RUN npm ci
COPY . .
Dependency manifests before source so install layers stay cached on source-only changes.
dockerfile
COPY package*.json ./
RUN npm ci
COPY . .
先复制依赖清单再复制源码,这样当仅源码变化时,安装依赖的镜像层会保持缓存。

BuildKit Secrets

BuildKit 密钥管理

dockerfile
RUN --mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa git clone git@github.com:org/repo.git
Secrets in
ENV
/
ARG
/
COPY
persist in layer history (
docker history
). Use
--mount=type=secret
.
dockerfile
RUN --mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa git clone git@github.com:org/repo.git
通过
ENV
/
ARG
/
COPY
设置的密钥会保留在镜像层历史中(可通过
docker history
查看)。请使用
--mount=type=secret
方式。

Docker Bake (Multi-Platform)

Docker Bake(多平台构建)

hcl
target "app" {
  platforms = ["linux/amd64", "linux/arm64"]
  cache-from = ["type=gha"]
  cache-to = ["type=gha,mode=max"]
}
hcl
target "app" {
  platforms = ["linux/amd64", "linux/arm64"]
  cache-from = ["type=gha"]
  cache-to = ["type=gha,mode=max"]
}

Security Anti-Patterns

安全反模式

Anti-patternFix
FROM image:latest
Pin version:
image:1.2.3-alpine
No
USER
directive
adduser
+
USER appuser
chmod 777
Use specific permissions:
chmod 550
privileged: true
in compose
Remove or use specific
cap_add
volumes: [/:/host]
Mount only needed paths
ports: ["0.0.0.0:3000:3000"]
Bind to
127.0.0.1:3000:3000
ENV DB_PASSWORD=secret
Use
--mount=type=secret
or compose secrets
反模式修复方案
FROM image:latest
固定版本:
image:1.2.3-alpine
未设置
USER
指令
使用
adduser
创建用户并设置
USER appuser
chmod 777
使用特定权限:
chmod 550
compose中设置
privileged: true
移除该配置或使用特定的
cap_add
volumes: [/:/host]
仅挂载所需路径
ports: ["0.0.0.0:3000:3000"]
绑定到
127.0.0.1:3000:3000
ENV DB_PASSWORD=secret
使用
--mount=type=secret
或compose密钥管理

CI Testing Gotchas

CI测试注意事项

  1. Bypass entrypoint:
    docker run --rm --entrypoint php myimage -v
  2. Mock upstream DNS:
    docker run --rm --add-host backend:127.0.0.1 nginx-image nginx -t
  3. Compose validation:
    cp .env.example .env
    before
    docker compose config
  4. Secret scanning: Exclude
    .env.example
    , README, docs from scanners
  1. 绕过入口点
    docker run --rm --entrypoint php myimage -v
  2. 模拟上游DNS
    docker run --rm --add-host backend:127.0.0.1 nginx-image nginx -t
  3. Compose验证:在执行
    docker compose config
    前复制
    .env.example
    .env
  4. 密钥扫描:将
    .env.example
    、README、文档排除在扫描范围外

.dockerignore

.dockerignore配置

Exclude:
.git
,
node_modules
/
vendor
,
.env*
,
*.pem
,
*.key
需排除的内容:
.git
node_modules
/
vendor
.env*
*.pem
*.key

Compose Essentials

Compose核心要点

  • depends_on
    with
    condition: service_healthy
    +
    healthcheck
    with
    start_period
    for startup ordering
  • networks
    with
    internal: true
    for database isolation from external access
  • profiles: [debug]
    for optional services that only start with
    --profile debug
  • 使用
    depends_on
    搭配
    condition: service_healthy
    ,并为依赖服务设置包含
    start_period
    healthcheck
    来控制启动顺序
  • 使用
    networks
    并设置
    internal: true
    实现数据库与外部访问隔离
  • 使用
    profiles: [debug]
    定义可选服务,仅在添加
    --profile debug
    参数时启动

References

参考资料

  • references/ci-testing.md
    -- Comprehensive CI testing patterns for Docker images
  • references/ci-testing.md
    -- Docker镜像的CI测试完整模式指南