Communitygithub.com

docker-patterns

Docker 和 Docker Compose 模式,用于本地开发、加固的 CLI 安装程序框架、容器安全、网络、卷以及多服务编排。在创建或审查 Dockerfile 和 Compose 服务、跨 Linux 发行版测试安装程序、或规划准确的本地 macOS 和 Windows 验证时使用。

docker-patterns 是什么?

该技能提供了全面的 Docker 和 Docker Compose 最佳实践指南,涵盖本地开发、生产部署、容器安全、网络隔离、卷策略以及加固的 CLI 安装程序测试框架。其主要价值在于提供了一个经过实战检验的模式库,帮助开发者避免常见的反模式,同时确保跨平台(Linux、macOS、Windows)的容器化应用的一致性和安全性。技能支持所有主流容器平台,并特别强调了在 CI/CD 环境中使用临时容器进行安全测试的方法论。该技能通过结构化的 YAML 和 Dockerfile 示例、清晰的隔离契约(如只读挂载、无网络模式、非 root 用户)以及详细的调试命令,使开发者能够快速构建可靠、安全的容器化工作流,并有效验证 CLI 工具的可移植性。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/docker-patterns

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Docker 模式

容器化开发的 Docker 和 Docker Compose 最佳实践。

适用于本地开发的 Docker Compose

标准 Web 应用栈

# docker-compose.yml
services:
  app:
    build:
      context: .
      target: dev                     # 使用多阶段 Dockerfile 的 dev 阶段
    ports:
      - "3000:3000"
    volumes:
      - .:/app                        # 用于热重载的绑定挂载
      - /app/node_modules             # 匿名卷 -- 保留容器依赖
    environment:
      - DATABASE_URL=postgres://postgres:postgres@db:5432/app_dev
      - REDIS_URL=redis://redis:6379/0
      - NODE_ENV=development
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    command: npm run dev

  db:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: app_dev
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data

  mailpit:                            # 本地邮件测试
    image: axllent/mailpit
    ports:
      - "8025:8025"                   # Web UI
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

开发 vs 生产 Dockerfile

# 阶段: 依赖
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# 阶段: dev (热重载, 调试工具)
FROM node:22-alpine AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# 阶段: build
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build && npm prune --production

# 阶段: production (最小化镜像)
FROM node:22-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
USER appuser
COPY --from=build --chown=appuser:appgroup /app/dist ./dist
COPY --from=build --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=build --chown=appuser:appgroup /app/package.json ./
ENV NODE_ENV=production
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]

覆盖文件

# docker-compose.override.yml (自动加载, 仅开发设置)
services:
  app:
    environment:
      - DEBUG=app:*
      - LOG_LEVEL=debug
    ports:
      - "9229:9229"                   # Node.js 调试器

# docker-compose.prod.yml (为生产显式指定)
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
# 开发 (自动加载覆盖)
docker compose up

# 生产
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

网络

服务发现

同一 Compose 网络中的服务通过服务名解析:

# 从 "app" 容器:
postgres://postgres:postgres@db:5432/app_dev    # "db" 解析到 db 容器
redis://redis:6379/0                             # "redis" 解析到 redis 容器

自定义网络

services:
  frontend:
    networks:
      - frontend-net

  api:
    networks:
      - frontend-net
      - backend-net

  db:
    networks:
      - backend-net              # 仅可从 api 访问, 不能从 frontend

networks:
  frontend-net:
  backend-net:

仅暴露所需端口

services:
  db:
    ports:
      - "127.0.0.1:5432:5432"   # 仅从宿主机可访问, 而非网络
    # 生产环境省略端口 -- 仅在 Docker 网络内可访问

卷策略

volumes:
  # 命名卷: 跨容器重启持久化, 由 Docker 管理
  pgdata:

  # 绑定挂载: 将宿主机目录映射到容器 (用于开发)
  # - ./src:/app/src

  # 匿名卷: 保留容器生成的内容, 避免被绑定挂载覆盖
  # - /app/node_modules

常见模式

services:
  app:
    volumes:
      - .:/app                   # 源代码 (用于热重载的绑定挂载)
      - /app/node_modules        # 保护容器的 node_modules 不受宿主机影响
      - /app/.next               # 保护构建缓存

  db:
    volumes:
      - pgdata:/var/lib/postgresql/data          # 持久数据
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化脚本

容器安全

Dockerfile 加固

# 1. 使用特定标签 (绝不使用 :latest)
FROM node:22.12-alpine3.20

# 2. 以非 root 用户运行
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app

# 3. 减少 capabilities (在 compose 中)
# 4. 尽可能使用只读根文件系统
# 5. 镜像层中不可包含密钥

Compose 安全

services:
  app:
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
      - /app/.cache
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE          # 仅当绑定到端口 < 1024 时需要

密钥管理

# 好: 使用环境变量 (运行时注入)
services:
  app:
    env_file:
      - .env                     # 切勿将 .env 提交到 git
    environment:
      - API_KEY                  # 从宿主机环境继承

# 好: Docker secrets (Swarm 模式)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  db:
    secrets:
      - db_password

# 坏: 硬编码在镜像中
# ENV API_KEY=sk-proj-xxxxx      # 切勿这样做

加固的 CLI 安装程序框架

使用容器来测试安装程序在一次性项目副本上的行为, 而不允许测试修改源检出。

尊重平台边界

  • 为 Linux 发行版 (如 Debian 和 Ubuntu) 运行真实容器。
  • macOS 不能作为 Docker 容器运行, 因为 Docker 共享 Linux 内核。在 macOS 上原生运行相同的无 shell 测试入口点。
  • Windows 容器需要 Windows Docker 引擎。在原生 Windows CI 运行器上运行平台无关的逻辑, 并将 Windows 容器保留给 Windows 宿主机。
  • 保留原生 Ubuntu/macOS/Windows CI 矩阵以测试宿主机特定路径、命令存根、引号和文件系统行为。

不要声称 Linux 容器可以验证 macOS 或 Windows 行为。

执行隔离契约

  • 通过不可变摘要固定基础镜像, 并固定安装的 CLI 版本。
  • 当发行版账户名不同时, 以非 root 数字 UID/GID 运行。
  • 以只读方式挂载仓库和源项目。
  • 在进行任何修改之前, 将源项目复制到可写的 tmpfs 工作区。
  • 使用 noexec, UID/GID 1000, 和 mode=0700 挂载 /workspace, 以便只有容器用户可以检查项目数据。
  • 将 npm 和 npx 的可执行缓存保留在 NPM_CONFIG_CACHE=/tmp/npm-cache 中的可执行 /tmp 挂载上。其默认大小为 2 GiB, 可通过 ECC_TMPFS_SIZE 调整;ECC_WORKSPACE_SIZE 单独控制私有工作区挂载。
  • 设置 read_only: true, no-new-privileges:true, cap_drop: [ALL] 和有限的 pids_limit。
  • 将默认的真实 CLI 服务保留在 network_mode: none 上。仅通过一个显式命名、选择加入的服务为经过身份验证的提供程序会话添加网络访问;切勿使其成为意外的环境驱动默认值。
  • 仅创建工具所需的可写临时路径。
  • 默认情况下, 不要将宿主机的凭据传递到容器中。
  • 默认执行 dry run, 并仅白名单显式的 dry-run, install, plugin 和 shell 模式。
  • 使用参数数组或 spawnSync(..., { shell: false }) 用于跨平台运行器。切勿将项目路径插值到 shell 命令中。

执行 ECC 插件设置框架

使用 docker/plugin-setup/compose.yaml 作为参考实现。它提供:

  • fixture-tests 用于专注的安装清单、目标和执行器套件。
  • real-cli 用于固定的基于 Debian 的通用 Linux 镜像。
  • real-cli-ubuntu 用于固定的 Ubuntu 镜像。

在构建之前验证 Compose 模型:

docker compose -f docker/plugin-setup/compose.yaml config --quiet

构建两个真实的 Linux 镜像:

docker compose -f docker/plugin-setup/compose.yaml \
  build real-cli real-cli-ubuntu

在每个镜像中运行安全默认流程:

docker compose -p ecc-plugin-debian-test \
  -f docker/plugin-setup/compose.yaml \
  run --rm -T real-cli dry-run

docker compose -p ecc-plugin-ubuntu-test \
  -f docker/plugin-setup/compose.yaml \
  run --rm -T real-cli-ubuntu dry-run

dry run 执行当前的公共命令契约:

ecc install --profile core --target claude-project --dry-run --json

在此命令运行之前, 容器从只读检出创建一个本地打包的 npm 工件, 使用 npm pack --ignore-scripts。它提取自创建的 tarball 到 /tmp, 验证 ecc-universal 包名、必需的安装清单和受限的 package.json bin.ecc 映射, 然后调用提取的 ecc 可执行文件。运行时保持在 network_mode: none 上, 不执行包生命周期脚本, 并且不依赖宿主机的 node_modules;其精确的固定生产依赖已存在于镜像中。

该框架拒绝空计划、非 claude-project 目标、/workspace/project/.claude 之外的任何操作、或任何创建目标目录的 dry run。install 执行两次隔离的应用, 检查其管理的安装状态, 列出已安装的目标, 并运行 doctor。

启动、打开、重连和清理命名会话

启动一个无 --rm 的分离容器, 这样离开终端不会移除会话:

docker compose -p ecc-plugin-session \
  -f docker/plugin-setup/compose.yaml \
  run --detach --name ecc-plugin-shell real-cli shell

容器将只读 fixture 复制到稳定的私有目录 /workspace/project。确认其运行中, 然后发出终端开启器 v1 数据契约的 Docker 端:

docker inspect --format '{{.State.Running}}' ecc-plugin-shell
node docker/plugin-setup/interactive-plan.js \
  --container ecc-plugin-shell \
  --workdir /workspace/project \
  --json \
  -- bash

JSON 结果正好有一个 executable 和 argv 边界 (外加 contractVersion: 1): 可执行文件是 docker, argv 以 exec, -it, 和 -w 开头。当单独的终端开启器技能安装后, 将这些数据传递给它。此 Docker 框架特意不导入终端适配器、不插值 shell 命令、也不管理宿主机 GUI 进程。在此之前, 直接在当前宿主机的终端中打开相同的 PTY:

docker exec -it -w /workspace/project ecc-plugin-shell bash

退出 shell 而不停止分离的容器。使用相同的 docker exec -it 命令重连。完成后, 删除确切的命名容器及其 Compose 项目资源:

docker rm --force ecc-plugin-shell
docker compose -p ecc-plugin-session \
  -f docker/plugin-setup/compose.yaml \
  down --remove-orphans

默认情况下没有宿主机的凭据, 并且从不挂载凭据目录。默认服务也没有网络访问。当经过身份验证的提供程序会话确实需要网络时, 首先构建 real-cli, 然后通过 docker compose --profile networked run real-cli-networked shell 显式选择加入。首选在该一次性会话内进行身份验证。如果 CI 运行必须继承宿主机环境凭据, 请在调用时通过显式的 Compose --env NAME 标志选择加入, 理解该值在容器的生命周期内是可检查且可被外泄的, 并立即删除确切的命名容器。

在宿主机上运行相同的专注套件:

npm run test:plugin-setup-platform

在信任镜像之前检查生成的标识和环境:

docker image inspect ecc-plugin-setup:debian ecc-plugin-setup:ubuntu

清理每个命名测试项目, 而不删除无关的卷或镜像:

docker compose -p ecc-plugin-debian-test \
  -f docker/plugin-setup/compose.yaml down --remove-orphans
docker compose -p ecc-plugin-ubuntu-test \
  -f docker/plugin-setup/compose.yaml down --remove-orphans

.dockerignore

node_modules
.git
.env
.env.*
dist
coverage
*.log
.next
.cache
docker-compose*.yml
Dockerfile*
README.md
tests/

调试

常用命令

# 查看日志
docker compose logs -f app           # 跟随 app 日志
docker compose logs --tail=50 db     # 最后 50 行 db 日志

# 在运行中的容器中执行命令
docker compose exec app sh           # 进入 app 容器 shell
docker compose exec db psql -U postgres  # 连接到 postgres

# 检查
docker compose ps                     # 运行中的服务
docker compose top                    # 每个容器中的进程
docker stats                          # 资源使用

# 重建
docker compose up --build             # 重建镜像
docker compose build --no-cache app   # 强制完全重建

# 清理
docker compose down                   # 停止并移除容器
docker compose down -v                # 同时移除卷 (具有破坏性)
docker system prune                   # 移除未使用的镜像/容器

调试网络问题

# 检查容器内的 DNS 解析
docker compose exec app nslookup db

# 检查连接性
docker compose exec app wget -qO- http://api:3000/health

# 检查网络
docker network ls
docker network inspect <project>_default

反模式

# 不好: 使用 :latest 标签
FROM node:latest

# 不好: 以 root 运行
USER root

# 不好: 在镜像层硬编码密钥
ENV API_KEY=supersecret

# 不好: 在 Dockerfile 中构建时从网络复制
ADD https://example.com/setup.sh /tmp/setup.sh

# 不好: 忽略 .dockerignore, 导致庞大上下文
docker build -t app .
# 应使用: docker build -t app -f Dockerfile .

跨平台验证矩阵

在真实操作系统上而不是容器内测试 macOS 和 Windows 特定行为。

  • Linux: 容器 (Docker)
  • macOS: 原生 CI 运行器 (GitHub Actions macos-*, CircleCI macos)
  • Windows: 原生 CI 运行器 (GitHub Actions windows-*, Azure DevOps windows)

不要在生产环境中使用 image: ubuntu:latest 来验证 macOS 路径格式。 在 Linux 容器中测试时, 使用通用路径 /workspace/project 并忽略特定于操作系统的引号行为。

参考

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

相关技能