depends_on ใน Docker Compose คืออะไร? กำหนดลำดับการ Start Container

depends_on คืออะไร?

depends_on เป็น option ใน Docker Compose ที่ใช้กำหนดความสัมพันธ์ระหว่าง Service ว่า Service ไหนต้องเริ่มก่อน Service ไหน เช่น Application Server ต้องรอให้ Database พร้อมก่อนจึงจะเริ่มทำงานได้

ปัญหาที่พบบ่อยคือ เมื่อรัน docker compose up พร้อมกันทุก Container ตัว App อาจพยายามเชื่อมต่อ Database ก่อนที่ Database จะพร้อมรับการเชื่อมต่อ ทำให้เกิด Error และ App ล้มเหลว

รูปแบบพื้นฐานของ depends_on

version: '3.8'
services:
  app:
    image: myapp:latest
    depends_on:
      - db
      - redis
  
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
  
  redis:
    image: redis:7-alpine

ในตัวอย่างนี้ service app จะไม่เริ่มต้นจนกว่า db และ redis จะถูก start ขึ้นมาก่อน

ข้อจำกัดของ depends_on แบบพื้นฐาน

depends_on แบบธรรมดาจะรอแค่ให้ Container เริ่มต้น (started) เท่านั้น ไม่ได้รอให้ Service พร้อมใช้งาน (healthy/ready) จริงๆ

เช่น MySQL Container อาจเริ่ม Process แล้ว แต่ยังไม่พร้อมรับ Connection ในช่วงแรก ทำให้ App ยังเชื่อมต่อไม่ได้

ใช้ condition เพื่อรอให้ Service พร้อม

Docker Compose รองรับ condition 3 แบบ:

  • service_started — รอแค่ให้ Container เริ่มต้น (ค่า default)
  • service_healthy — รอให้ Healthcheck ผ่าน
  • service_completed_successfully — รอให้ Service ทำงานเสร็จและออกด้วย exit code 0

ตัวอย่าง: รอ MySQL จนกว่าจะ Healthy

version: '3.8'
services:
  app:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
  
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: mydb
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
  
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

อธิบาย Healthcheck แต่ละ Option

Option ความหมาย ค่าแนะนำ
test คำสั่งที่ใช้ทดสอบ ขึ้นอยู่กับ Service
interval ระยะเวลาระหว่างการทดสอบ 10s-30s
timeout เวลาสูงสุดที่รอผล 3s-10s
retries จำนวนครั้งที่ลองซ้ำก่อนถือว่า unhealthy 3-5
start_period เวลาให้ Service เริ่มต้นก่อนนับ retries 10s-60s

ตัวอย่าง: Web App + PostgreSQL + Redis

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://user:password@postgres:5432/mydb
      REDIS_URL: redis://redis:6379
  
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
      interval: 10s
      timeout: 5s
      retries: 5
  
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

volumes:
  postgres_data:

depends_on กับ restart policy

แนะนำใช้ร่วมกับ restart: on-failure หรือ restart: unless-stopped เพื่อให้ App ลอง restart ถ้าเชื่อมต่อ Database ไม่ได้ในครั้งแรก

  app:
    image: myapp:latest
    restart: on-failure
    depends_on:
      db:
        condition: service_healthy

service_completed_successfully ใช้เมื่อไหร่?

เหมาะสำหรับ Migration หรืองาน Init ที่ต้องทำก่อน Application จะเริ่ม:

services:
  migrate:
    image: myapp:latest
    command: python manage.py migrate
    depends_on:
      db:
        condition: service_healthy
  
  app:
    image: myapp:latest
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy

สรุป

การใช้ depends_on ร่วมกับ condition: service_healthy และ healthcheck เป็นวิธีที่ถูกต้องที่สุดในการจัดการลำดับการเริ่มต้น Container ใน Docker Compose ช่วยให้แน่ใจว่า Service ทุกตัวพร้อมใช้งานจริงก่อน Application จะเริ่มทำงาน