云上栖息地 - 部署
type: channel
link: https://alwaysray.com/tag/%E9%83%A8%E7%BD%B2/
items: Docker Compose 多容器部署：依赖管理实战

Docker Compose 多容器部署：依赖管理实战
type: item
date: 2026-07-22T10:13:43+08:00
description: 部署一个 Python + Redis + Nginx 的服务，容器启动顺序搞错了。Redis 还没 ready，Python 服务就报 Connection refused。排查了半天，发现是 depends_on 只保证容器启动顺序，不保证服务就绪。问题现象# docker-compose.yml services: web: build: . depends_on: - redis ports: - "8000:8000" redis: image: redis:7-alpine ports: - "6379:6379" docker-compose up -d Python 服务启动后报错：redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused. 坑在于：depends_on 只保证 Redis 容器先启动，不保证 Redis 服务已经就绪。Redis 容器启动了，但 Redis 服务可能还在初始化。解决方案方案一：healthcheck + condition（推荐）services: web: build: . depends_on: redis: condition: service_healthy ports: - "8000:8000" redis: image: redis:7-alpine ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 healthcheck 定义健康检查命令，condition: service_healthy 等待 Redis 健康后再启动 web。方案二：启动脚本等待# app.py import redis import time def wait_for_redis(host, port, max_retries=30): """等待 Redis 就绪""" for i in range(max_retries): try: r = redis.Redis(host=host, port=port) r.ping() print("Redis 已就绪") return r except redis.ConnectionError: print(f"等待 Redis... ({i+1}/{max_retries})") time.sleep(1) raise Exception("Redis 连接超时") r = wait_for_redis("redis", 6379) 坑在于：这个方案需要在应用代码里加等待逻辑，不够优雅。方案三：wait-for-it 脚本services: web: build: . depends_on: - redis command: > sh -c "wait-for-it -t 30 redis:6379 -- python app.py" ports: - "8000:8000" # Dockerfile FROM python:3.11-slim # 安装 wait-for-it RUN apt-get update && apt-get install -y wait-for-it && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . 这个方案需要在镜像里安装 wait-for-it，增加镜像体积。完整配置示例Python + Redis + Nginxservices: web: build: . depends_on: redis: condition: service_healthy environment: - REDIS_HOST=redis - REDIS_PORT=6379 ports: - "8000:8000" redis: image: redis:7-alpine ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 volumes: - redis_data:/data nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/e…