一个真实应用很少是单个容器:Web 服务要连数据库,数据库要挂数据卷,也许还有缓存和任务队列。用一连串 docker run 维护这些,命令越攒越长、参数越记越乱。Docker Compose 把整套应用写进一个 YAML 文件,docker compose up -d 一条命令完整拉起。
示例场景:Web + PostgreSQL + Redis
目标架构:一个 Web 应用,连接 PostgreSQL 存数据、Redis 做缓存;数据库数据要持久化;Redis 不对外暴露端口。
services: web: image: registry.example.com/myapp:1.4.2 build: . ports: - "8080:8080" environment: DATABASE_URL: postgres://myapp:${DB_PASSWORD}@db:5432/myapp REDIS_URL: redis://cache:6379/0 depends_on: db: condition: service_healthy cache: condition: service_started restart: unless-stopped networks: - appnet
db: image: postgres:16 environment: POSTGRES_USER: myapp POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: myapp volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U myapp"] interval: 5s timeout: 3s retries: 10 restart: unless-stopped networks: - appnet
cache: image: redis:7 restart: unless-stopped networks: - appnet
volumes: pgdata:
networks: appnet:保存为 compose.yml(新版标准文件名,旧的 docker-compose.yml 同样兼容),同目录执行:
docker compose up -d # 创建并后台启动全部服务docker compose ps # 查看服务状态docker compose logs -f web # 跟踪某个服务日志docker compose down # 停止并删除容器与网络(数据卷保留)docker compose down -v # 连数据卷一起删(危险操作)关键配置项逐条解释
build 与 image 共存:build: . 表示用当前目录构建;同时写 image: 则构建产物以该名字存储。有现成镜像时省略 build。
depends_on 的正确用法:默认只保证启动顺序,不保证「数据库真的就绪了」。Web 应用在 Postgres 还没初始化完时启动照样崩。正确姿势是 condition: service_healthy 配合数据库的 healthcheck——Compose 会等到健康检查通过才启动依赖方。
服务名即主机名:同一 network 下的服务可以用服务名互相访问。DATABASE_URL 里的 @db:5432 和 redis://cache:6379 就是靠这个机制,不需要写死 IP。
端口映射的最小暴露原则:只有 web 映射了宿主端口;db 和 cache 不写 ports,外界(包括宿主机之外的机器)就无法访问它们,天然隔离。
环境变量与密钥管理
Compose 自动读取同目录的 .env 文件做变量替换:
# .env(不要提交到 Git)DB_PASSWORD=s3cure-random-string${DB_PASSWORD} 在 YAML 里被替换成实际值。纪律:
.env加入.gitignore,仓库里只放.env.example模板。- 不要在 YAML 里直接写明文密码——这个文件通常会进版本库。
- 不同环境用多个文件区分:
docker compose --env-file .env.prod up -d。
日常运维操作速查
# 重新构建并更新某个服务(改了代码后)docker compose up -d --build web
# 在服务容器里执行一次性命令(如数据库迁移)docker compose exec web ./migrate up
# 临时跑一个一次性容器docker compose run --rm web ./bin/console
# 看整体资源占用docker compose top多份 Compose 文件做环境分层
开发环境要挂源码、开调试端口,生产不要。用多文件叠加而不是复制整份配置:
docker compose -f compose.yml -f compose.dev.yml up -ddocker compose -f compose.yml -f compose.prod.yml up -d后面的文件覆盖前面的同名配置。compose.dev.yml 里给 web 加源码挂载,生产文件里加资源限制,公共部分只维护一份。
Compose 的边界
Compose 解决的是单机多容器编排。它的定位很清晰:开发环境、小项目部署、CI 集成测试。需要跨机器调度、自动扩缩容、滚动更新时,就该上 Kubernetes 了——那是下一篇文章的话题。但即便上了 K8s,本地开发用 Compose 起一套依赖依然是高效的做法。
延伸阅读
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 6 天
部分内容可能已过时