Docker Compose:一条命令运行多个服务
如何在一个文件中描述应用、数据库和 Web 服务器的组合,用一条命令启动,并在无需手动重建的情况下更新。
更新于 2026年8月23日
您可以用一条很长的 docker run 命令启动单个服务。但两个需要互相访问的服务就不行了:第二天您就会忘记那些参数。Compose 把整个描述搬进一个文件,您可以阅读、编辑,并保存在仓库中。
最小示例
/opt/myapp 目录,其中包含 compose.yaml:
services:
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: app
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
retries: 5
app:
image: ghcr.io/example/app:1.4.2
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/app
ports:
- "127.0.0.1:8080:8080"
volumes:
db-data:
旁边是 .env 文件:
DB_PASSWORD=long-random-password
chmod 600 .env
docker compose up -d
docker compose ps
docker compose logs -f app
这里的关键点
- 用名称代替地址。 应用通过名称
db访问数据库——Compose 会创建一个共享网络,服务名称在其中自动解析。您不需要把数据库端口对外发布,也不应该这样做。 restart: unless-stopped。 没有它,机器重启后什么都不会自动恢复。- 带健康检查的
depends_on。 普通的depends_on只等待容器启动,而不等待数据库准备好接受连接。应用会提前启动并崩溃。 - 精确的镜像版本。 用
postgres:17,而不是postgres:latest。使用latest,某次pull会带来一个无法打开旧数据的主版本。 - 在
127.0.0.1上发布。 只有通过带证书的 Web 服务器才对外暴露端口。
日常命令
docker compose up -d # bring up or apply changes
docker compose down # stop and remove containers (volumes intact)
docker compose down -v # ...and remove volumes too
docker compose restart app # restart one service
docker compose exec app sh # go inside
docker compose pull && docker compose up -d # update images
docker compose config # show final file with substitutions
docker compose config 是启动前检查文件的最佳方式:它会显示变量展开成了什么,以及是否有缩进丢失。
docker compose down -v会连同数据库一起删除卷。这是不可逆的。在执行任何带-v的操作之前,请确认您有副本——参见备份。
环境文件
用叠加文件把同一套栈区分测试和生产很方便:
docker compose -f compose.yaml -f compose.prod.yaml up -d
第二个文件只覆盖差异部分:内存限制、发布的端口和日志级别。