用 Docker Compose 编排多服务应用(进阶)

一个 compose.yaml 管好 web、数据库、缓存:自定义网络、健康检查、环境变量、数据卷与重启策略。

单个容器很好起,但真实应用往往是「web + 数据库 + 缓存」的组合。手动 docker run 一个个拉起来既繁琐又容易漏配网络。Docker Compose 用一份声明式的 compose.yaml 把这些服务、网络和数据卷一次性描述清楚,一条命令拉起整套栈。本文假设你在自己的服务器/VPS 上,系统为 Ubuntu/Debian,已装好 Docker Engine 与 Compose 插件(docker compose version 能输出版本即可)。

一个 web + db + redis 的例子

在项目目录新建 compose.yaml:

services:
  web:
    build: .
    ports:
      - "8080:8080"
    environment:
      DATABASE_URL: "postgres://app:${DB_PASSWORD}@db:5432/appdb"
      REDIS_URL: "redis://cache:6379"
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    networks:
      - backend
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: appdb
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - backend
    restart: unless-stopped

  cache:
    image: redis:7
    networks:
      - backend
    restart: unless-stopped

volumes:
  db-data:

networks:
  backend:

自定义网络让服务互通

networks 段声明了一个自定义桥接网络 backend,三个服务都接入它。同一网络内,Compose 会做服务名 DNS 解析:web 直接用主机名 db、cache 就能访问对方,无需暴露端口到宿主机。只有真正要对外的 web 才用 ports 把 8080 映射出去,db 和 cache 留在内网更安全。

dependson 与 healthcheck

dependson 控制启动顺序,但默认只等容器「启动」,不等它「就绪」。数据库进程起来到能接受连接之间有空窗,所以给 db 加 healthcheck(用 pgisready 探活),再让 web 用 condition: servicehealthy 等数据库真正健康后再启动,避免首次连接被拒。

环境变量与 .env

把密码等配置抽出来。同目录建一个 .env,Compose 会自动读取:

DB_PASSWORD=change-me-in-prod

compose.yaml 里的 ${DBPASSWORD} 会被替换。记得把 .env 加进 .gitignore,别提交到仓库。

数据卷持久化

容器删掉后文件系统就没了,数据库必须挂命名卷:db-data:/var/lib/postgresql/data。卷由 Docker 托管,docker compose down 也不会删,重建容器数据仍在(除非显式 down -v)。

重启策略

restart: unless-stopped 让容器崩溃或服务器重启后自动拉起,但你手动停掉的除外。生产常用它;想崩溃就重试可用 on-failure。

常用命令

docker compose up -d          # 后台拉起整套栈
docker compose ps             # 查看状态
docker compose logs -f web    # 跟踪某个服务日志
docker compose up -d --scale web=3   # 把 web 横向扩到 3 个副本
docker compose down           # 停止并删除容器(保留命名卷)

注意 --scale 时不能再给该服务写死 ports 单端口(会冲突),通常前面挂个反向代理或用端口范围。

小结

Compose 的价值是把「多容器怎么协作」写成一份可版本化的文件:自定义网络让服务用名字互访,healthcheck + dependson 保证启动次序,.env 收口配置,命名卷守住数据,restart 提供自愈。掌握 up -d、logs -f、scale 这几条命令,你就能在任何一台 VPS 上稳定地跑起一套多服务应用。