关于 docker-development
docker-development 是一份面向 Docker 开发与 CI 的实践指南,涵盖镜像构建、安全、缓存、Compose 和测试排错。它通过简短示例与专题参考,帮助开发者处理容器项目的常见工程问题。
主要功能
- 01Node.js 与 Go 多阶段构建示例
- 02镜像与容器安全建议
- 03构建缓存和 Docker Bake 指引
- 04Compose 生命周期与配置要点
- 05CI 测试和常见故障排查
- 06专题参考文档索引
适用场景
- 01为 Node.js 或 Go 服务设计多阶段镜像
- 02检查容器配置中的密钥与权限风险
- 03优化依赖安装层的构建缓存
- 04排查 Compose 服务状态和 CI 测试问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ netresearch/ docker-development-skill --skill docker-development安装后在 Claude Code 中输入/docker-development确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
checkpoints.yamlreferences/bake-ci-cache.mdbind-mount-ownership.mdbuild-secret-leaks.mdci-testing.mdcompose-runtime-lifecycle.mddatabase-container-readiness.mddind-testing-patterns.mdengine-and-image-upgrades.mdgpg-verification.mdimage-ca-trust.mdmulti-stage-caching.mdphp-fpm-worker-starvation.mdregistry-catalogue-and-pin-rot.md详细介绍
Docker 开发
核心原则
- 精简 —— 使用 Alpine/distroless、多阶段构建
- 安全 —— 使用非 root 用户,不在层中存放密钥,固定版本
- 可测试 —— 绕过入口点,模拟 DNS
- 缓存高效 —— 优先处理依赖,在同一层中清理
快速参考
多阶段构建(Node.js)
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
FROM node:24-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"]
多阶段构建(Go —— scratch/distroless)
FROM golang:1.26-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"]
层优化
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
构建缓存:先复制依赖文件
COPY package*.json ./
RUN npm ci
COPY . .
先复制清单再复制源代码,可保持安装层的缓存。
BuildKit 密钥
RUN --mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa git clone [email protected]:org/repo.git
ARG 会通过 docker history 和 SLSA provenance 泄露——
references/build-secret-leaks.md
Docker Bake(多平台)
target "app" {
platforms = ["linux/amd64", "linux/arm64"]
}
CI 构建通过 Bake 和 netresearch/.github/.github/workflows/build-container-bake.yml@main 进行,可构建一个或多个镜像。可复用工作流会为每个目标添加 GHA 缓存,因此 HCL 中无需声明;定时重建时会传入 cache: false——references/bake-ci-cache.md
安全反模式
| 反模式 | 修复方法 |
|---|---|
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 测试注意事项
- 绕过入口点:
docker run --rm --entrypoint php myimage -v - 模拟上游 DNS:
docker run --rm --add-host backend:127.0.0.1 nginx-image nginx -t - 验证 Compose 配置:运行
docker compose config前先执行cp .env.example .env - 密钥扫描:排除
.env.example、README 和文档 - 由 root 拥有的文件:绑定挂载目录(
EACCES)——references/bind-mount-ownership.md
.dockerignore
排除:.git、node_modules/vendor、.env*、*.pem、*.key
Compose 要点
- 启动顺序:
depends_on.condition: service_healthy+healthcheckstart_period networks.internal: true可隔离数据库profiles: [debug]:仅在使用--profile debug时启动。down和--remove-orphans会忽略已禁用配置文件中的容器,因此停止启用某项服务后,该服务仍会继续运行——使用docker compose --profile '*' down,或docker compose down <service>(references/compose-runtime-lifecycle.md)- 日志驱动默认会阻塞:远程端点(如
awslogs)卡住时,应用的写入也会停滞;mode: non-blocking+max-buffer-size会改为丢弃日志行,仅保护正在运行的容器(references/compose-runtime-lifecycle.md) - 共享镜像引用:在每个文件中仅定义一次,作为顶层扩展字段并使用锚点——
x-app-image: &app-image registry/app:${APP_IMAGE_VERSION:-85},服务使用image: *app-image。该字段必须位于services:上方——别名只有在文档顺序中位于锚点之后才有效。:-默认值会覆盖未设置和空变量(省略标签时会静默解析为:latest)。锚点仅限当前文件:每个覆盖文件都需要自己的锚点。验证这两种情况:APP_IMAGE_VERSION= docker compose config以及使用覆盖值的情况
参考资料
references/bake-ci-cache.md—— 共享的 bake 可复用项;在 Compose 文件旁使用-f docker-bake.hcl;按目标划分 GHA 缓存作用域;不使用缓存但仍会写入缓存的定时重建;bake-action 目录中的辅助步骤references/ci-testing.md—— Docker 镜像的 CI 测试模式;-c字符串中使用 busyboxsh而非 bash;在docker compose run外使用timeout,当 PID 1 忽略信号时,容器仍会运行references/dind-testing-patterns.md—— Docker-in-Docker 测试模式references/bind-mount-ownership.md—— 归 root 所有的绑定挂载产物;父路径上的 tmpfs 会遮蔽其下方的卷references/gpg-verification.md—— gpgv 模式;过期的 keybox 锁references/registry-catalogue-and-pin-rot.md—— 目录探测;版本固定失效references/build-secret-leaks.md—— provenance 中的ARGreferences/php-fpm-worker-starvation.md—— keepalive 会占用 php-fpmreferences/engine-and-image-upgrades.md——MinAPIVersion会阻止读取套接字的 sidecar;探测容器升级检查;基础镜像更改USER;PHP 8.5 OPcache 内置于核心references/database-container-readiness.md—— 已植入数据的 DB 镜像会将ready for connections记录两次;验证植入的数据,而非日志references/compose-runtime-lifecycle.md—— 已禁用 profile 的容器会在down和up --remove-orphans后继续存在;阻塞式与非阻塞式日志传递,以及非阻塞式日志传递无法防护的情况references/image-ca-trust.md—— CA 遭到入侵后:测量已发布镜像的ca-certificates版本和根证书主题;在证书包中用grep搜索 CA 名称总会返回 0
评论
支持 Markdown