关于 docker-compose-setup
这项技能用于通过 Docker Compose 设计和配置多容器应用栈。内容涵盖服务依赖、网络、持久化存储、健康检查,以及开发和生产环境的不同设置。
主要功能
- 01梳理服务及其依赖
- 02配置镜像、端口和变量
- 03设置网络与服务发现
- 04管理持久化卷和挂载
- 05添加健康检查与启动顺序
- 06创建环境专属覆盖配置
适用场景
- 01定义多服务应用栈
- 02持久保存数据库和上传数据
- 03按依赖协调服务启动
- 04区分开发与生产设置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ seb1n/ awesome-ai-agent-skills --skill docker-compose-setup安装后在 Claude Code 中输入/docker-compose-setup确认已加载。
详细介绍
Docker Compose 配置
此技能可让 Agent 使用 Docker Compose 设计和配置多容器应用程序堆栈。Agent 可以编排 Web 服务器、数据库、缓存、后台工作进程和反向代理等服务,并正确配置网络、卷管理、健康检查以及特定环境的覆盖配置。Agent 了解开发和生产环境配置,并能生成符合 Docker 最佳实践的 compose 文件。
工作流
-
分析应用程序堆栈: Agent 会检查项目架构,以确定所有必需服务及其依赖项。这包括主应用程序容器、数据库(PostgreSQL、MySQL、MongoDB)、缓存(Redis、Memcached)、消息队列(RabbitMQ、Kafka)、后台工作进程以及反向代理(Nginx、Traefik)。Agent 会梳理服务间的依赖关系,以确定启动顺序和健康检查要求。
-
定义服务和镜像: 对于每项服务,Agent 会指定 Docker 镜像或构建上下文、公开的端口、环境变量和资源限制。应用程序服务通常使用指向本地 Dockerfile 的
build指令,而基础设施服务则使用带固定版本标签的官方镜像。Agent 会避免在生产环境中使用latest标签,以确保部署可复现。 -
配置网络和服务发现: Agent 会创建命名 Docker 网络,以隔离不同服务层之间的流量(例如,为代理和应用创建
frontend网络,为应用和数据库创建backend网络)。服务使用 compose 服务名称作为 DNS 主机名进行通信,无需硬编码 IP 地址。 -
设置卷和持久化: Agent 会为必须在容器重启后保留的数据定义命名卷,例如数据库存储和文件上传。对于开发环境,会使用绑定挂载将主机源代码映射到容器中,以支持热重载。Agent 会确保卷权限和所有权针对容器运行时用户进行了正确配置。
-
添加健康检查并设置依赖顺序: Agent 会为关键服务配置健康检查,使依赖服务在其依赖项真正就绪后再启动,而不只是等待其启动。这可以避免应用程序容器在数据库虽已启动但尚未接受连接时发生崩溃等常见问题。使用带有
condition: service_healthy的depends_on指令可确保正确的启动顺序。 -
创建特定环境的覆盖配置: Agent 会生成基础
docker-compose.yml,用于共享配置,并生成覆盖文件(开发环境使用docker-compose.override.yml,生产环境使用docker-compose.prod.yml),以便按环境自定义设置。开发环境覆盖配置包括绑定挂载、调试端口和详细日志记录;生产环境覆盖配置则包括资源限制、重启策略和经过优化的日志驱动程序。
支持的技术
- Compose 版本: Docker Compose V2(集成的 Docker CLI 插件)
- 应用程序运行时: Node.js、Python、Ruby、Go、Java、PHP、.NET
- 数据库: PostgreSQL、MySQL、MariaDB、MongoDB、Redis、Elasticsearch
- 反向代理: Nginx、Traefik、Caddy、HAProxy
- 消息队列: RabbitMQ、Kafka、NATS
- 监控: Prometheus、Grafana、cAdvisor
用法
向 Agent 提供应用程序堆栈的说明,包括所需的服务、它们之间的关系,以及配置用于开发还是生产环境。
示例提示词:
Create a docker-compose setup for my Node.js app with:
- PostgreSQL database with persistent storage
- Redis for session caching
- Nginx reverse proxy with SSL termination
- A Celery-like background worker process
- Development setup with hot reloading
示例
示例 1:全栈 Web 应用程序(Node.js + PostgreSQL + Redis + Nginx)
services:
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/certs:/etc/nginx/certs:ro
depends_on:
app:
condition: service_healthy
networks:
- frontend
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
app:
build:
context: .
dockerfile: Dockerfile
environment:
NODE_ENV: production
DATABASE_URL: postgres://appuser:${DB_PASSWORD}@postgres:5432/myapp
REDIS_URL: redis://redis:6379
SESSION_SECRET: ${SESSION_SECRET}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- frontend
- backend
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1))"]
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
worker:
build:
context: .
dockerfile: Dockerfile
command: node worker.js
environment:
DATABASE_URL: postgres://appuser:${DB_PASSWORD}@postgres:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
volumes:
postgres_data:
redis_data:
networks:
frontend:
backend:
示例 2:开发与生产环境的覆盖配置
docker-compose.yml(基础共享配置):
services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
DATABASE_URL: postgres://appuser:${DB_PASSWORD}@postgres:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
networks:
- backend
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
networks:
backend:
docker-compose.override.yml(开发环境——自动加载):
services:
app:
build:
target: development
ports:
- "3000:3000"
- "9229:9229" # Node.js debug port
volumes:
- .:/app
- /app/node_modules
environment:
NODE_ENV: development
DEBUG: "app:*"
command: npm run dev
postgres:
ports:
- "5432:5432" # Expose DB to host for local tooling
docker-compose.prod.yml(生产环境——通过 -f 使用):
services:
app:
build:
target: production
restart: unless-stopped
environment:
NODE_ENV: production
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.5"
memory: 256M
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
postgres:
restart: unless-stopped
deploy:
resources:
limits:
cpus: "2.0"
memory: 1G
使用以下命令运行生产环境:docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
最佳实践
- 使用命名卷保存持久化数据: 不要依赖容器内部存储来保存数据库或上传文件。命名卷在容器重新创建后仍会保留,也可以单独备份。
- 固定镜像版本: 始终指定明确的镜像标签(例如
postgres:16-alpine),而不是latest,以避免镜像更新时出现意外的重大变更。 - 为每项服务配置健康检查: 健康检查可让 Docker 检测容器是否处于不健康状态,并支持使用
depends_on和condition: service_healthy实现可靠的启动顺序。如果没有健康检查,依赖服务可能会在其依赖项就绪前启动。 - 使用
.env文件保存密钥: 将数据库密码和 API 密钥等敏感值存储在.env文件中,并通过.gitignore将该文件排除在版本控制之外。在 compose 文件中使用${VARIABLE}语法引用变量。 - 按层划分网络: 使用不同的网络隔离流量。反向代理不应能够直接访问数据库。这样可以限制容器遭到入侵后的影响范围。
- 通过覆盖配置保持 compose 文件 DRY: 使用基础配置加覆盖配置的模式,而不是为每个环境复制整个 compose 文件。这样可以确保共享的服务定义保持同步。
边缘情况
- 主机端口冲突: 如果主机端口已被占用(例如,另一项服务正在使用 5432 端口),Docker Compose 将无法绑定端口。请使用唯一的主机端口,或者为只需通过 Docker 网络与容器通信的服务设置
ports: []。 - 卷权限不匹配: 以非 root 用户身份运行的容器,如果主机目录权限受限,可能无法写入挂载的卷。请在 compose 文件中使用
user:指令,或在 Dockerfile 的入口点中使用chown,使 UID/GID 保持一致。 - 构建缓存失效: 在 Dockerfile 前面的部分更改
COPY或ADD指令,会使之后所有层的缓存失效。请按更改频率从低到高排列 Dockerfile 指令(先列依赖项,再列源代码),以最大限度地复用缓存。 - 启动期间的容器 DNS 解析: 服务可能会在依赖容器分配 IP 地址之前解析其 DNS 名称,从而导致连接失败。使用带有
depends_on条件的健康检查可以避免此问题,但仍建议在应用程序层实现重试逻辑。 - 孤立的容器和卷: 从 compose 文件中移除某项服务后再运行
docker compose up,会留下仍在运行的孤立容器。请使用docker compose up --remove-orphans,并定期运行docker volume prune清理未使用的卷。