在 Docker Compose 中控制 "Nginx+MySQL+Redis" 多容器应用的启动顺序,需通过以下方法实现依赖管理:

1. 基础依赖控制 (depends_on)

docker-compose.yml 中声明服务间的启动顺序:

services:
  nginx:
    depends_on:
      - mysql
      - redis
    # Nginx配置...

  mysql:
    # MySQL配置...

  redis:
    # Redis配置...

此配置确保:

  • MySQL 和 Redis 在 Nginx 之前启动
  • 不保证 MySQL/Redis 完全就绪后才启动 Nginx

2. 健康检查 + 依赖条件

添加健康检查确保服务真正可用:

services:
  mysql:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 3s
      timeout: 2s
      retries: 5

  nginx:
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy

此时 Nginx 会等待:

  • MySQL 返回 healthy 状态(通过 mysqladmin ping 验证)
  • Redis 返回 healthy 状态(通过 redis-cli ping 验证)

3. 启动脚本控制

在 Nginx 容器中使用启动脚本检测依赖服务:

#!/bin/bash
# wait-for-services.sh

until nc -z mysql 3306; do
  echo "等待 MySQL 启动..."
  sleep 2
done

until nc -z redis 6379; do
  echo "等待 Redis 启动..."
  sleep 1
done

exec nginx -g "daemon off;"  # 启动Nginx

在 Dockerfile 中配置:

COPY wait-for-services.sh /app/
CMD ["sh", "/app/wait-for-services.sh"]

完整示例

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

  redis:
    image: redis:6
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 3s
      timeout: 2s
      retries: 5

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    volumes:
      - ./wait-for-services.sh:/app/wait.sh
    command: ["sh", "/app/wait.sh"]

关键注意事项

  1. 网络别名:确保所有服务在同一个网络,使用服务名作为主机名(如 mysql:3306
  2. 超时设置:健康检查中的 timeoutretries 需根据服务启动时间调整
  3. Compose 版本:需使用 v2.1+ 才支持 condition: service_healthy
  4. 日志验证:通过 docker-compose logs 观察启动顺序

此方案确保 Nginx 仅在 MySQL 和 Redis 完全就绪后启动,避免因依赖服务未准备好导致的连接失败问题。实际部署时可根据服务特性调整健康检查命令和超时参数。

更多推荐