Docker Compose:37K+ Star 多容器应用编排完整指南
Docker Compose(docker compose)用声明式 YAML 定义和运行多容器应用。兼容 Docker、Traefik、Prometheus、Grafana。涵盖安装、生产加固、健康检查和与 Kubernetes/Podman/Nomad 对比。
- ⭐ 37744
- 更新于 2026-08-27
用原始 docker run 命令管理多容器应用快速崩溃。典型 Web 栈需要数据库、缓存、反向代理和应用本身——那是四个需要互相连接的独立容器带网络、卷和环境变量。Docker Compose 用单个声明式 YAML 文件解决此问题。37,000+ GitHub stars,它仍是本地开发和单节点生产部署采用最广的工具。本教程涵盖从安装到生产加固的一切,附可立即部署的真实配置。
🔗 GitHub: https://github.com/docker/compose
什么是 Docker Compose? #
Docker Compose 是用声明式 YAML 配置文件(通常 compose.yaml)定义和运行多容器 Docker 应用的工具。它自动处理服务发现、网络创建、卷挂载和启动顺序——将容器定义文件夹转为单命令可运行系统。
Docker Compose 工作原理 #
架构简单。你写 compose.yaml 文件描述服务、网络 and 卷。docker compose CLI 插件读取此文件并转为 Docker Engine API 调用。幕后发生:
- 项目隔离:Compose 创建专用 Docker 网络名为
<project>_<network>(默认:目录名 +_default)。项目所有服务通过此隔离桥接网络通信。 - 服务发现:容器通过服务名互相访问。你有
db服务,你的api容器连db:5432无需任何 DNS 配置。 - 卷管理:命名卷在容器重启间持久化数据。Compose 用项目名前缀卷名避免冲突。
- 依赖排序:
depends_on指令控制启动序列。结合condition: service_healthy,确保数据库在应用启动前就绪。 - 资源生命周期:
docker compose up创建一切;docker compose down拆除。加--volumes移除持久数据,或--rmi all清理镜像。
现代 Compose 规范(v2.x+,基于 Go)是滚动规范——version: 顶层键不再需要。规范文件名从 docker-compose.yml 移到 compose.yaml,两者为向后兼容都接受。
安装与设置 #
Docker Compose v2 作为 CLI 插件随 Docker Engine 捆绑。传统基于 Python 的 docker-compose(v1)二进制 2023 年弃用且不再维护。
Linux(Ubuntu/Debian) #
# 更新包索引
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 添加仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker Engine + Compose 插件
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# 添加用户到 docker 组(需注销)
sudo usermod -aG docker $USER
newgrp docker
# 验证
docker compose version
# 预期:Docker Compose version v2.36.0+
macOS #
从 docker.com 下载 Docker Desktop。Docker Compose 捆绑。Apple Silicon 上,Docker Desktop 用 Virtualization.framework 比传统 QEMU 后端性能高 30-40%。
# 安装后验证
docker compose version
Windows(WSL2) #
# 启用 WSL2
wsl --install
# 重启,然后安装带 WSL2 后端的 Docker Desktop
docker compose version
手动二进制安装 #
无包管理器环境:
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.36.0/docker-compose-linux-x86_64 \
-o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
docker compose version
与流行工具集成 #
Traefik(反向代理与负载均衡) #
Traefik 自动发现 Docker 容器并基于标签路由流量。消除手动 nginx 配置:
# compose.yaml — Traefik + Whoami 示例
name: proxy-demo
services:
traefik:
image: traefik:v3.3
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
whoami:
image: traefik/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
用 docker compose up -d 启动,访问 http://whoami.localhost。
Prometheus + Grafana(监控栈) #
# compose.yaml — 监控栈
name: monitoring
services:
prometheus:
image: prom/prometheus:v3.2.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
grafana:
image: grafana/grafana:11.5.0
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
Prometheus 抓取容器指标;Grafana 可视化。登录后添加 Prometheus 数据源到 http://prometheus:9090。
全栈应用(PostgreSQL + Redis + FastAPI + Nginx) #
# compose.yaml — 生产就绪 3 层应用
name: myapp
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: appdb
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
restart: unless-stopped
api:
build:
context: ./api
dockerfile: Dockerfile
environment:
DATABASE_URL: postgresql://appuser:***@db:5432/appdb
REDIS_URL: redis://redis:6379/0
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
restart: unless-stopped
nginx:
image: nginx:1.27-alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
api:
condition: service_healthy
restart: unless-stopped
volumes:
postgres_data:
redis_data:
展示关键模式:健康检查依赖、命名卷持久化、自定义镜像构建上下文、restart: unless-stopped 韧性。
基准测试 / 真实用例 #
Docker Compose 在特定场景卓越。以下来自生产部署和对比的数字:
| 指标 | Docker Compose | Kubernetes | Podman Compose | Nomad |
|---|---|---|---|---|
| 控制平面 RAM | ~50 MB | ~2 GB | 0 MB(无守护进程) | ~100 MB |
| 支持节点 | 单节点 | 无限 | 单节点 | 无限 |
| 每项目服务 | 典型 1-50 | 1-10,000+ | 典型 1-50 | 1-1,000+ |
| 首次部署时间 | < 5 分钟 | 2-8 小时 | < 5 分钟 | 30-60 分钟 |
| 3 层应用 YAML 行数 | ~40 | ~200+(Deployments + Services) | ~40 | ~80 |
| 自动伸缩 | 手动(docker compose up –scale) | 原生 HPA | 手动 | 原生 |
| 滚动更新 | 仅重建 | 原生 | 仅重建 | 原生 |
启动速度:Docker Compose 在 4 核机器 10 秒内启动 5 服务栈。等效 Kubernetes 部署带 Helm 含 pod 调度需 60-120 秒。
资源效率:Compose 开销约 CLI + Docker 守护进程 50 MB RAM。最小 Kubernetes 控制平面运行任何工作负载前消耗 ~2 GB。单节点下 10 服务以下部署,Compose 用 40 倍少编排开销。
CI/CD 采用:90%+ GitHub Actions 工作流用容器依赖 Docker Compose 做集成测试环境。docker compose up --wait 命令(等待健康状态)消除竞态条件引起的脆弱测试管道。
高级用法 / 生产加固 #
健康检查与启动排序 #
无健康检查永不上生产。容器显示 Up 状态仅意味着进程启动——不意味着你的应用工作:
services:
api:
image: myapp:v1.2.3
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8080/ready"]
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
depends_on:
db:
condition: service_healthy
restart: unless-stopped
日志轮转 #
无限 JSON 日志填满磁盘。配置带轮转的本地日志驱动:
services:
api:
image: myapp:v1.2.3
logging:
driver: "local"
options:
max-size: "10m"
max-file: "3"
compress: "true"
资源限制 #
防止一个失控容器饿死其他:
services:
worker:
image: myapp-worker:v1.2.3
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
配置文件环境分离 #
用配置文件定义仅开发服务无需维护多文件:
services:
api:
image: myapp:latest
ports:
- "8080:8080"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: devpass
pgadmin:
image: dpage/pgadmin4:latest
profiles: ["debug"]
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@local.dev
PGADMIN_DEFAULT_PASSWORD: admin
需要时运行调试工具:docker compose --profile debug up -d。无标志时跳过 pgadmin。
密钥管理 #
切勿将密码提交到你的 compose 文件。用 Docker 密钥或环境变量文件:
services:
api:
image: myapp:latest
secrets:
- db_password
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
include 指令(Compose v2.20+) #
将大项目拆为模块化 compose 文件:
# compose.yaml — 根文件
name: platform
include:
- path: ./infra/postgres.yaml
- path: ./infra/redis.yaml
- path: ./apps/api.yaml
- path: ./apps/worker.yaml
env_file: ./apps/worker.env
每个包含文件是有效 compose 文件带自己服务、网络和卷。这保持单文件 50 行下使代码审查可管理。
蓝绿部署 #
无 Kubernetes 零停机更新,用两个 compose 项目和反向代理:
#!/bin/bash
# deploy.sh
CURRENT=$(cat /tmp/current_slot 2>/dev/null || echo "blue")
NEW=$([ "$CURRENT" = "blue" ] && echo "green" || echo "blue")
# 构建并启动新槽
docker compose -p "app-${NEW}" -f compose.yaml up -d --build --wait
# 更新 nginx 上游
sed -i "s/app-${CURRENT}/app-${NEW}/g" /etc/nginx/conf.d/upstream.conf
nginx -s reload
# 拆除旧槽
docker compose -p "app-${CURRENT}" -f compose.yaml down
# 持久活跃槽
echo "$NEW" > /tmp/current_slot
与替代对比 #
| 功能 | Docker Compose | Kubernetes | Podman + Compose | Nomad |
|---|---|---|---|---|
| 学习曲线 | 低(单 YAML) | 高(多资源) | 低(Docker CLI 兼容) | 中(HCL 配置) |
| 多节点 | 否(单主机) | 是 | 否(单主机) | 是 |
| 需要守护进程 | 是(dockerd) | 是(kubelet + 控制平面) | 否(无守护进程) | 是(Nomad 代理) |
| 默认无 root | 否 | 否 | 是 | 可选 |
| 自动伸缩 | 仅手动 | 原生 HPA | 仅手动 | 原生 |
| 存储卷 | 仅本地 | CSI 插件(任何后端) | 仅本地 | 主机 + CSI |
| 密钥管理 | 基于文件 env | 原生密钥 + Vault | 基于文件 env | Vault 集成 |
| 社区规模 | 37K+ stars | 110K+(kubernetes/kubernetes) | 23K+(containers/podman) | 15K+(hashicorp/nomad) |
| 最佳用途 | 开发、CI/CD、小生产 | 大规模生产 | 安全优先、无 root | 混合工作负载 |
| 许可 | Apache-2.0 | Apache-2.0 | Apache-2.0 | BUSL(源可用) |
局限 / 诚实评估 #
Docker Compose 非万能方案。以下它不足:
单节点约束:Compose 运行在一主机。主机故障你整个栈宕机。高可用需求你需要 Kubernetes、Nomad 或 Docker Swarm。
无原生自动伸缩:docker compose up --scale api=3 工作,但是手动。无基于 CPU 或内存的水平 pod 自动伸缩如 Kubernetes HPA。
有限密钥管理:基于文件的 Docker 密钥对单节点设置可接受。缺旋转、静态加密和 Kubernetes 密钥或 HashiCorp Vault 提供的细粒度 RBAC。
滚动更新基础:Compose 重建容器。不能做金丝雀部署、流量拆分或回滚到前副本集。关键任务零停机部署用更 sophisticated 编排器。
网络仅本地:默认桥接网络一主机内工作。多主机服务网格、ingress 控制器和跨域负载均衡需 Kubernetes 或服务网格如 Istio。
守护进程依赖:不同于 Podman,Compose 需要 Docker 守护进程(dockerd)运行。守护进程是单点故障和监管环境潜在安全担忧。
常见问题 #
Q: 我的 compose 文件还需要 version: "3.8" 行吗?
A: 不需要。Compose 规范现在无版本。version 键在 Compose v2.x+ 和 v5.x 被忽略。新项目应完全省略它并用 compose.yaml 作为文件名。带 version 行的旧版 docker-compose.yml 文件仍为向后兼容工作。
Q: docker-compose 和 docker compose 区别?
A: docker-compose(带连字符)是传统基于 Python 的 v1 二进制,2023 年弃用且不再维护。docker compose(带空格)是 v2 CLI 插件用 Go 编写,积极维护、更快并与 Docker Engine 捆绑。所有新脚本和 CI 管道应使用 docker compose。
Q: 如何生产运行 Docker Compose 不停机?
A: Docker Compose 无内置滚动更新。实用方法是:(1) 接受 docker compose up -d 期间短暂停机用于内部工具,(2) 用高级用法节显示蓝绿部署脚本带两个 compose 项目和反向代理,或 (3) 零停机是硬性要求时迁移到 Kubernetes 或 Nomad。
结论 #
Docker Compose 是本地开发和小型生产部署的行业标准。通过 37,000+ GitHub stars 和简单 YAML 声明式配置,它让开发者快速运行多容器应用而无需 Kubernetes 复杂度。
💬 留言讨论