Communitygithub.com

docker-patterns

Docker 與 Docker Compose 模式,涵蓋本地開發、強化 CLI 安裝器測試、容器安全、網路、磁碟區以及多服務協作。在建立或審查 Dockerfile 與 Compose 服務、於多種 Linux 發行版測試安裝器,或規劃準確的原生 macOS 與 Windows 驗證時使用。

docker-patterns 是什麼?

這份 Docker Patterns 技能提供一套全面且務實的容器化開發最佳實踐指南,特別著重於本地開發的 Docker Compose 配置、多階段 Dockerfile 設計、容器安全強化,以及嚴謹的 CLI 安裝器測試流程。對於使用 Claude Code、Cursor 或 Codex 等 AI 代理的開發者來說,這份指南能幫助你快速生成安全、高效且可維護的容器化環境,避免常見的反模式,例如以 root 執行、提升權限或洩漏機密。該技能詳細說明了如何透過 Immutable Digest 鎖定基底映像、使用非 root 使用者、限制容器能力(cap_drop),以及掌控暫存檔案系統(tmpfs)來隔離測試產生的變更,確保不影響原始專案。 技能內容涵蓋多個平台:Linux 容器可在任何 Docker 主機上執行;macOS 與 Windows 需以原生方式驗證,因為 Docker 容器無法模擬這些作業系統的核心。它特別設計了一套「隔離測試合約」,要求將原始碼唯讀掛載,並複製到可寫入的 tmpfs 工作區才進行變更,從而保護開發環境的完整性。此外,也提供了啟動、中斷、重新連線及清理命名容器的標準流程,並強調網路與憑證的安全預設值。這套技能是開發 AI 代理工具、進行多平台 CI/CD 測試,以及建立穩健容器化工作流程的必備參考。

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

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Docker 模式

適用於容器化開發的 Docker 與 Docker Compose 最佳實踐。

本地開發的 Docker Compose

標準網頁應用程式堆疊

# 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"                   # 網頁介面
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

開發 vs 生產環境的 Dockerfile

# Stage: dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# Stage: dev (熱重載、除錯工具)
FROM node:22-alpine AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Stage: 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

# Stage: 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"   # 僅主機能存取,對外網路不可見
    # 正式環境省略 ports 設定——僅能在 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. 移除權限 (在 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 機密 (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、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

試運行執行目前的公開指令合約:

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

在執行該指令之前,容器會使用 npm pack --ignore-scripts 從唯讀的檢出中建立本地打包的 npm 構件。它將自建的 tarball 解壓縮到 /tmp 下,驗證 ecc-universal 套件名稱、必要的安裝清單和限制的 package.json bin.ecc 對應,然後呼叫解壓縮後的 ecc 可執行檔。執行環境保持在 network_mode: none,不執行套件生命週期腳本,也不依賴主機的 node_modules;其鎖定的確切生產依賴項已存在於映像中。

該框架拒絕空白的計劃、非 claude-project 的目標、在 /workspace/project/.claude 之外的任何操作,或任何會建立目標目錄的試運行。install 會執行兩次隔離的應用,檢查其管理的安裝狀態,列出已安裝的目標,並執行 doctor。

啟動、打開、重新連接和清理命名的工作階段

啟動一個分離的容器(不使用 --rm),以便離開終端時不會移除工作階段:

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

容器將唯讀的固定資料複製到穩定的私有目錄 /workspace/project。確認它正在執行,然後輸出 Docker 端的終端打開器 v1 資料合約:

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     # 顯示 db 最近 50 行

# 在執行中的容器執行指令
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

反模式

# 不良:使…

[為翻譯而截斷]

注意:原始內容在反模式部分被截斷。請參考完整來源以獲得更多資訊。

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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相關技能