掌握了 Compose 的基本用法后,你可能需要更精细的控制:自定义网络、确保服务就绪后再启动、区分开发与生产环境等。本文将深入讲解 Compose 的网络模型、depends_on 的局限与健康检查方案、环境变量使用技巧,以及如何通过多个 Compose 文件实现配置复用和环境隔离。

一、自定义网络
默认情况下,Compose 会为项目创建一个默认网络(格式 <项目名>_default)。但有时需要:

隔离服务:让某些服务只能内部通信,不暴露。

连接外部容器:与其它 Compose 项目共享网络。

指定 IP 地址范围。

1.1 创建自定义网络

version: '3.8'

services:
  web:
    image: nginx
    networks:
      - frontend
  api:
    image: myapi
    networks:
      - frontend
      - backend
  db:
    image: mysql
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true   # 禁止外部访问(仅内部服务可通)

说明:

frontend 网络允许外部访问(默认 bridge),backend 网络设为 internal: true,只有 api 和 db 能相互通信。

服务可以连接到多个网络,实现网关模式。

1.2 连接到外部已有网络

networks:
  external_net:
    external: true   # 使用已存在的网络,不会创建

二、依赖控制与健康检查
depends_on 仅控制服务启动顺序,并不等待服务真正就绪。例如数据库启动需要几秒钟,而 Web 应用在这期间连接数据库会失败。

解决方案:使用 healthcheck 和 condition。

2.1 在 Dockerfile 中定义健康检查
dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD mysqladmin ping -h localhost -u root -p$MYSQL_ROOT_PASSWORD || exit 1
2.2 Compose 中使用 depends_on 的 condition

version: '3.8'

services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: example
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    image: myweb
    depends_on:
      db:
        condition: service_healthy

condition 可选值:

service_started:等价于默认行为(仅启动)。

service_healthy:等待健康检查通过。

service_completed_successfully:等待任务容器成功退出。

注意:condition 需要 Compose 文件版本 ≥ 2.3 或 3.x,但 Swarm 模式下部分不支持。对于本地开发,可搭配 wait-for-it.sh 脚本。

三、环境变量与 .env 文件
Compose 支持两种方式管理环境变量:

直接在 environment 字段硬编码(不推荐用于敏感信息)。

使用 env_file 引用外部文件(适合开发/生产分离)。

示例:

services:
  web:
    image: nginx
    env_file:
      - ./common.env
      - ./web.env

同时,Compose 会自动加载项目目录下的 .env 文件(如果存在),并用于替换 Compose 文件中的变量。

# .env 内容
MYSQL_ROOT_PASSWORD=secret
# docker-compose.yml
services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}

四、扩展:多个 Compose 文件
对于不同环境(开发、测试、生产),可以使用多个 Compose 文件叠加。例如:

docker-compose.yml:基础服务定义。

docker-compose.override.yml:开发环境覆盖(自动合并)。

docker-compose.prod.yml:生产环境配置。

用法:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

示例:

docker-compose.yml:

services:
  web:
    image: myapp
    ports:
      - "3000:3000"

docker-compose.prod.yml:

services:
  web:
    restart: always
    environment:
      NODE_ENV: production

合并后 web 服务将同时拥有 ports、restart 和 environment。

五、配置文件中的变量替换
Compose 支持使用 Shell 环境变量或 .env 文件中的变量。例如:

services:
  web:
    image: myapp:${TAG:-latest}

如果 TAG 未设置,使用默认值 latest。

安全提醒:不要将敏感变量(如密码)直接写在 .env 并提交到版本控制。使用 Secret 管理工具或运行时注入。

六、实战:多环境 Compose 配置
项目结构:

text
.
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
└── .env
docker-compose.yml(公共部分):

version: '3.8'
services:
  app:
    build: .
    volumes:
      - .:/app
  db:
    image: postgres
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:

docker-compose.dev.yml(开发覆盖):

services:
  app:
    environment:
      - DEBUG=true
    ports:
      - "5000:5000"
  db:
    ports:
      - "5432:5432"

docker-compose.prod.yml(生产覆盖):

services:
  app:
    restart: always
    environment:
      - DEBUG=false
    logging:
      driver: json-file
      options:
        max-size: 10m
  db:
    restart: always

启动开发环境:

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

生产环境(可能需要额外环境变量):

export TAG=v1.0
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

七、常用命令进阶
命令	作用
docker-compose config	验证并查看合并后的 Compose 配置
docker-compose up --build	重新构建镜像并启动
docker-compose up --scale web=3	启动 3 个 web 容器(需无端口冲突或使用负载均衡)
docker-compose down -v	删除容器和关联的卷(清理完全)
docker-compose run --rm  	临时运行一次性命令

八、小结
本文介绍了 Compose 的高级用法:自定义网络实现服务隔离,健康检查确保依赖就绪,环境变量管理配置,以及多文件扩展适配不同环境。这些技巧让你从“能用”走向“精通”,能够应对复杂的本地开发和测试场景。

更多推荐