Docker Compose: คู่มือการใช้งานฉบับสมบูรณ์

แนะนำ Docker Compose

Docker Compose เป็นเครื่องมือที่ใช้สำหรับการกำหนดและรันแอปพลิเคชันที่ประกอบด้วย Docker containers หลายตัว โดยใช้ไฟล์ YAML เพียงไฟล์เดียวในการกำหนดค่าทั้งหมด ช่วยให้การจัดการ multi-container applications ทำได้ง่ายและสะดวกขึ้น

ข้อดีของ Docker Compose

สถาปัตยกรรมของ Docker Compose

graph TB
    A[docker-compose.yml] --> B[Docker Compose CLI]
    B --> C[Docker Engine]
    C --> D[Container 1: Web App]
    C --> E[Container 2: Database]
    C --> F[Container 3: Cache]
    D --> G[Network: app-network]
    E --> G
    F --> G
    D --> H[Volume: app-data]
    E --> I[Volume: db-data]

การติดตั้ง

Linux

# ดาวน์โหลดเวอร์ชันล่าสุด
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# ให้สิทธิ์ execute
sudo chmod +x /usr/local/bin/docker-compose

# ตรวจสอบการติดตั้ง
docker-compose --version

macOS และ Windows

Docker Compose มาพร้อมกับ Docker Desktop แล้ว ไม่ต้องติดตั้งแยก

ตรวจสอบเวอร์ชัน

docker compose version
# หรือ
docker-compose version

คำสั่งพื้นฐาน

1. docker compose up

สร้างและเริ่มต้น containers

# รัน containers แบบ foreground
docker compose up

# รัน containers แบบ background (detached mode)
docker compose up -d

# สร้าง images ใหม่ก่อนรัน
docker compose up --build

# รัน service เฉพาะ
docker compose up web

# Scale service
docker compose up --scale web=3

2. docker compose down

หยุดและลบ containers, networks

# หยุดและลบ containers และ networks
docker compose down

# ลบ volumes ด้วย
docker compose down -v

# ลบ images ที่สร้างจาก compose
docker compose down --rmi all

# ลบทุกอย่างรวม orphan containers
docker compose down --volumes --remove-orphans

3. docker compose ps

แสดงรายการ containers ที่กำลังทำงาน

# แสดง containers ทั้งหมด
docker compose ps

# แสดงทั้งที่รันและหยุดอยู่
docker compose ps -a

# แสดงแบบละเอียด
docker compose ps --services

4. docker compose logs

ดู logs ของ containers

# ดู logs ทั้งหมด
docker compose logs

# ดู logs แบบ real-time
docker compose logs -f

# ดู logs ของ service เฉพาะ
docker compose logs web

# ดู logs จำนวนบรรทัดล่าสุด
docker compose logs --tail=100 web

# แสดง timestamp
docker compose logs -t

5. docker compose exec

รันคำสั่งใน container ที่กำลังทำงานอยู่

# เข้าไปใน container แบบ interactive
docker compose exec web bash

# รันคำสั่งเดียว
docker compose exec web ls -la

# รันคำสั่งโดยไม่ allocate TTY
docker compose exec -T db pg_dump -U postgres mydb > backup.sql

6. docker compose run

สร้าง container ใหม่และรันคำสั่ง

# รัน one-off command
docker compose run web python manage.py migrate

# รันโดยไม่สร้าง dependencies
docker compose run --no-deps web python manage.py test

# ลบ container หลังรันเสร็จ
docker compose run --rm web python script.py

7. docker compose start/stop/restart

จัดการ containers ที่มีอยู่แล้ว

# เริ่ม containers ที่หยุดอยู่
docker compose start

# หยุด containers (ไม่ลบ)
docker compose stop

# รีสตาร์ท containers
docker compose restart

# จัดการ service เฉพาะ
docker compose restart web

8. docker compose build

สร้าง images

# สร้าง images ทั้งหมด
docker compose build

# สร้างโดยไม่ใช้ cache
docker compose build --no-cache

# สร้าง service เฉพาะ
docker compose build web

# สร้างแบบ parallel
docker compose build --parallel

9. docker compose pull

ดึง images จาก registry

# ดึง images ทั้งหมด
docker compose pull

# ดึง service เฉพาะ
docker compose pull web

10. docker compose config

ตรวจสอบ configuration

# แสดง configuration ที่ parsed แล้ว
docker compose config

# ตรวจสอบ syntax
docker compose config --quiet

# แสดงเฉพาะ services
docker compose config --services

โครงสร้างไฟล์ docker-compose.yml

โครงสร้างพื้นฐาน

version: '3.8'  # เวอร์ชันของ Compose file format

services:       # กำหนด containers ต่างๆ
  service_name:
    # การกำหนดค่า service

networks:       # กำหนด networks (optional)
  network_name:
    # การกำหนดค่า network

volumes:        # กำหนด volumes (optional)
  volume_name:
    # การกำหนดค่า volume

คำสั่งที่สำคัญใน service

1. image

ระบุ image ที่จะใช้

services:
  web:
    image: nginx:latest

2. build

สร้าง image จาก Dockerfile

services:
  web:
    build:
      context: ./dir              # directory ที่มี Dockerfile
      dockerfile: Dockerfile.dev  # ชื่อ Dockerfile (default: Dockerfile)
      args:                       # build arguments
        VERSION: "1.0"
      target: production          # build stage

3. container_name

ตั้งชื่อ container

services:
  web:
    container_name: my-web-app

4. ports

กำหนด port mapping (host:container)

services:
  web:
    ports:
      - "8080:80"        # HTTP
      - "443:443"        # HTTPS
      - "3000-3005:3000-3005"  # port range

5. volumes

กำหนด volume mounts

services:
  web:
    volumes:
      - ./app:/var/www/html          # bind mount
      - app-data:/var/lib/data       # named volume
      - /var/run/docker.sock:/var/run/docker.sock:ro  # read-only

6. environment

กำหนด environment variables

services:
  web:
    environment:
      - NODE_ENV=production
      - DEBUG=false
      - API_KEY=your-api-key
    # หรือใช้แบบ dictionary
    environment:
      NODE_ENV: production
      DEBUG: "false"

7. env_file

โหลด environment variables จากไฟล์

services:
  web:
    env_file:
      - .env
      - .env.production

8. depends_on

กำหนด service dependencies

services:
  web:
    depends_on:
      - db
      - redis
  db:
    image: postgres
  redis:
    image: redis

9. networks

กำหนด networks ที่ service เชื่อมต่อ

services:
  web:
    networks:
      - frontend
      - backend

10. restart

กำหนดนโยบายการรีสตาร์ท

services:
  web:
    restart: always          # รีสตาร์ทเสมอ
    # restart: unless-stopped  # รีสตาร์ทเว้นแต่หยุดด้วยตนเอง
    # restart: on-failure      # รีสตาร์ทเมื่อ error
    # restart: no              # ไม่รีสตาร์ท (default)

11. command

Override default command

services:
  web:
    command: python app.py --debug
    # หรือแบบ array
    command: ["python", "app.py", "--debug"]

12. healthcheck

ตรวจสอบสุขภาพของ container

services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

ตัวอย่างการใช้งานแบบละเอียด

ตัวอย่างที่ 1: Single Service - Simple Web Server

สร้างไฟล์ docker-compose.yml:

version: '3.8'

services:
  web:
    image: nginx:alpine
    container_name: simple-web
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped

สร้างไฟล์ html/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Docker Compose Demo</title>
</head>
<body>
    <h1>Hello from Docker Compose!</h1>
</body>
</html>

ขั้นตอนการรัน:

# 1. สร้าง directory structure
mkdir -p html
echo "<h1>Hello from Docker Compose!</h1>" > html/index.html

# 2. รัน container
docker compose up -d

# 3. ตรวจสอบสถานะ
docker compose ps

# 4. ทดสอบ
curl http://localhost:8080

# 5. ดู logs
docker compose logs -f

# 6. หยุดและลบ
docker compose down

ตัวอย่างที่ 2: Web Application + Database

สร้างโครงสร้างโปรเจค:

myapp/
├── docker-compose.yml
├── .env
├── app/
│   ├── Dockerfile
│   └── app.py
└── init.sql

ไฟล์ docker-compose.yml:

version: '3.8'

services:
  # Flask Web Application
  web:
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: flask-app
    ports:
      - "5000:5000"
    environment:
      - FLASK_ENV=development
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@db:5432/myapp
    volumes:
      - ./app:/app
      - app-logs:/var/log
    depends_on:
      - db
    networks:
      - app-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  # PostgreSQL Database
  db:
    image: postgres:15-alpine
    container_name: postgres-db
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=myapp
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - app-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # pgAdmin (optional)
  pgadmin:
    image: dpage/pgadmin4:latest
    container_name: pgadmin
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@example.com
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD}
    ports:
      - "5050:80"
    depends_on:
      - db
    networks:
      - app-network
    volumes:
      - pgadmin-data:/var/lib/pgadmin

networks:
  app-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  db-data:
    driver: local
  app-logs:
    driver: local
  pgadmin-data:
    driver: local

ไฟล์ .env:

# Database
DB_PASSWORD=mysecretpassword

# pgAdmin
PGADMIN_PASSWORD=admin123

ไฟล์ app/Dockerfile:

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Install curl for healthcheck
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

# Copy application
COPY . .

EXPOSE 5000

CMD ["python", "app.py"]

ไฟล์ app/requirements.txt:

Flask==3.0.0
psycopg2-binary==2.9.9
python-dotenv==1.0.0

ไฟล์ app/app.py:

from flask import Flask, jsonify
import psycopg2
import os

app = Flask(__name__)

def get_db_connection():
    conn = psycopg2.connect(os.environ.get('DATABASE_URL'))
    return conn

@app.route('/')
def home():
    return jsonify({
        'message': 'Welcome to Flask + PostgreSQL App',
        'status': 'running'
    })

@app.route('/health')
def health():
    try:
        conn = get_db_connection()
        conn.close()
        return jsonify({'status': 'healthy', 'database': 'connected'}), 200
    except Exception as e:
        return jsonify({'status': 'unhealthy', 'error': str(e)}), 500

@app.route('/users')
def get_users():
    try:
        conn = get_db_connection()
        cur = conn.cursor()
        cur.execute('SELECT id, name, email FROM users;')
        users = cur.fetchall()
        cur.close()
        conn.close()
        
        return jsonify({
            'users': [
                {'id': user[0], 'name': user[1], 'email': user[2]}
                for user in users
            ]
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

ไฟล์ init.sql:

-- Create users table
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Insert sample data
INSERT INTO users (name, email) VALUES
    ('John Doe', 'john@example.com'),
    ('Jane Smith', 'jane@example.com'),
    ('Bob Wilson', 'bob@example.com')
ON CONFLICT (email) DO NOTHING;

ขั้นตอนการรันแบบละเอียด:

# 1. สร้างโครงสร้าง directories
mkdir -p myapp/app
cd myapp

# 2. สร้างไฟล์ทั้งหมดตามด้านบน

# 3. ตรวจสอบ configuration
docker compose config

# 4. สร้าง images
docker compose build

# 5. รัน services ทั้งหมด
docker compose up -d

# 6. ตรวจสอบสถานะ
docker compose ps

# 7. ดู logs แบบ real-time
docker compose logs -f

# 8. ทดสอบ web application
curl http://localhost:5000
curl http://localhost:5000/health
curl http://localhost:5000/users

# 9. เข้าไปใน container
docker compose exec web bash

# 10. ทดสอบ database connection
docker compose exec db psql -U postgres -d myapp -c "SELECT * FROM users;"

# 11. ดู logs เฉพาะ service
docker compose logs db
docker compose logs web

# 12. รีสตาร์ท service เฉพาะ
docker compose restart web

# 13. Scale web service (ถ้าไม่มี container_name)
# docker compose up -d --scale web=3

# 14. หยุดทั้งหมด
docker compose stop

# 15. เริ่มใหม่
docker compose start

# 16. ลบทั้งหมดรวม volumes
docker compose down -v

สถาปัตยกรรมของตัวอย่างที่ 2

graph LR
    A[Client] -->|Port 5000| B[Flask Web App]
    A -->|Port 5050| C[pgAdmin]
    B -->|app-network| D[PostgreSQL DB]
    C -->|app-network| D
    B -.->|Volume Mount| E[./app]
    B -.->|Volume| F[app-logs]
    D -.->|Volume| G[db-data]
    D -.->|Init SQL| H[./init.sql]
    C -.->|Volume| I[pgadmin-data]

ตัวอย่างที่ 3: Full Stack Application (React + Node.js + MongoDB)

โครงสร้างโปรเจค:

fullstack-app/
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
├── .env
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── backend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
└── nginx/
    └── nginx.conf

ไฟล์ docker-compose.yml (Base configuration):

version: '3.8'

services:
  # Frontend - React
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: ${BUILD_TARGET:-development}
    volumes:
      - ./frontend/src:/app/src
      - /app/node_modules
    environment:
      - REACT_APP_API_URL=http://localhost:4000/api

  # Backend - Node.js + Express
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    volumes:
      - ./backend/src:/app/src
      - /app/node_modules
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - MONGODB_URI=mongodb://mongo:27017/myapp
      - JWT_SECRET=${JWT_SECRET}
      - PORT=4000

  # Database - MongoDB
  mongodb:
    image: mongo:7
    volumes:
      - mongo-data:/data/db
      - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USER}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD}
      - MONGO_INITDB_DATABASE=myapp

  # Mongo Express (Database GUI)
  mongo-express:
    image: mongo-express:latest
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_ROOT_USER}
      - ME_CONFIG_MONGODB_ADMINPASSWORD=${MONGO_ROOT_PASSWORD}
      - ME_CONFIG_MONGODB_URL=mongodb://${MONGO_ROOT_USER}:${MONGO_ROOT_PASSWORD}@mongodb:27017/
    depends_on:
      - mongodb

volumes:
  mongo-data:

networks:
  default:
    name: fullstack-network
    driver: bridge

ไฟล์ docker-compose.dev.yml (Development overrides):

version: '3.8'

services:
  frontend:
    ports:
      - "3000:3000"
    command: npm start
    environment:
      - CHOKIDAR_USEPOLLING=true  # For hot reload

  backend:
    ports:
      - "4000:4000"
      - "9229:9229"  # Debug port
    command: npm run dev
    environment:
      - DEBUG=app:*

  mongodb:
    ports:
      - "27017:27017"

  mongo-express:
    ports:
      - "8081:8081"

ไฟล์ docker-compose.prod.yml (Production overrides):

version: '3.8'

services:
  frontend:
    build:
      target: production
    restart: always

  backend:
    restart: always
    command: npm start
    environment:
      - NODE_ENV=production

  mongodb:
    restart: always
    command: mongod --auth

  # Nginx Reverse Proxy
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certbot/conf:/etc/letsencrypt:ro
      - ./certbot/www:/var/www/certbot:ro
    depends_on:
      - frontend
      - backend
    restart: always

ไฟล์ frontend/Dockerfile:

# Development stage
FROM node:18-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

# Build stage
FROM development AS build
RUN npm run build

# Production stage
FROM nginx:alpine AS production
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

ไฟล์ backend/Dockerfile:

FROM node:18-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm install

# Copy source code
COPY . .

EXPOSE 4000

# Development command (will be overridden by docker-compose)
CMD ["npm", "run", "dev"]

ไฟล์ .env:

# Environment
NODE_ENV=development
BUILD_TARGET=development

# MongoDB
MONGO_ROOT_USER=admin
MONGO_ROOT_PASSWORD=secretpassword

# Backend
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production

การรันแบบต่างๆ:

# Development mode
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# Production mode
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# ดู logs ทั้งหมด
docker compose logs -f

# ดู logs เฉพาะ service
docker compose logs -f backend

# Rebuild และรันใหม่
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build

# หยุดและลบ
docker compose down -v

สถาปัตยกรรมของ Full Stack Application

graph TB
    subgraph "Client Browser"
        A[User]
    end
    
    subgraph "Docker Network"
        subgraph "Frontend"
            B[React App
Port 3000] end subgraph "Backend" C[Node.js API
Port 4000] end subgraph "Database" D[MongoDB
Port 27017] E[Mongo Express
Port 8081] end subgraph "Production Only" F[Nginx
Reverse Proxy
Port 80/443] end end A -->|HTTP| B A -->|HTTP| F F -->|Proxy| B F -->|Proxy| C B -->|API Calls| C C -->|Queries| D E -->|Admin UI| D

ตัวอย่างที่ 4: Microservices Architecture

graph TB
    subgraph "API Gateway"
        A[Kong Gateway]
    end
    
    subgraph "Services"
        B[User Service]
        C[Product Service]
        D[Order Service]
        E[Payment Service]
    end
    
    subgraph "Databases"
        F[Users DB
PostgreSQL] G[Products DB
MongoDB] H[Orders DB
PostgreSQL] end subgraph "Message Queue" I[RabbitMQ] end subgraph "Monitoring" J[Prometheus] K[Grafana] end A --> B A --> C A --> D A --> E B --> F C --> G D --> H D --> I E --> I B --> J C --> J D --> J E --> J J --> K

ไฟล์ docker-compose.microservices.yml:

version: '3.8'

services:
  # API Gateway
  kong:
    image: kong:latest
    environment:
      - KONG_DATABASE=postgres
      - KONG_PG_HOST=kong-db
      - KONG_PG_USER=kong
      - KONG_PG_PASSWORD=kong
    ports:
      - "8000:8000"  # HTTP
      - "8443:8443"  # HTTPS
      - "8001:8001"  # Admin API
    depends_on:
      - kong-db
    networks:
      - microservices

  kong-db:
    image: postgres:15
    environment:
      - POSTGRES_USER=kong
      - POSTGRES_PASSWORD=kong
      - POSTGRES_DB=kong
    volumes:
      - kong-db-data:/var/lib/postgresql/data
    networks:
      - microservices

  # User Service
  user-service:
    build: ./services/user-service
    environment:
      - DATABASE_URL=postgresql://postgres:password@user-db:5432/users
      - RABBITMQ_URL=amqp://rabbitmq:5672
    depends_on:
      - user-db
      - rabbitmq
    networks:
      - microservices
    deploy:
      replicas: 2

  user-db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=users
      - POSTGRES_PASSWORD=password
    volumes:
      - user-db-data:/var/lib/postgresql/data
    networks:
      - microservices

  # Product Service
  product-service:
    build: ./services/product-service
    environment:
      - MONGODB_URI=mongodb://mongo:27017/products
      - RABBITMQ_URL=amqp://rabbitmq:5672
    depends_on:
      - mongo
      - rabbitmq
    networks:
      - microservices
    deploy:
      replicas: 2

  # Order Service
  order-service:
    build: ./services/order-service
    environment:
      - DATABASE_URL=postgresql://postgres:password@order-db:5432/orders
      - RABBITMQ_URL=amqp://rabbitmq:5672
      - USER_SERVICE_URL=http://user-service:3000
      - PRODUCT_SERVICE_URL=http://product-service:3000
    depends_on:
      - order-db
      - rabbitmq
    networks:
      - microservices

  order-db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=orders
      - POSTGRES_PASSWORD=password
    volumes:
      - order-db-data:/var/lib/postgresql/data
    networks:
      - microservices

  # Payment Service
  payment-service:
    build: ./services/payment-service
    environment:
      - RABBITMQ_URL=amqp://rabbitmq:5672
      - STRIPE_API_KEY=${STRIPE_API_KEY}
    depends_on:
      - rabbitmq
    networks:
      - microservices

  # MongoDB for Product Service
  mongo:
    image: mongo:7
    volumes:
      - mongo-data:/data/db
    networks:
      - microservices

  # RabbitMQ Message Broker
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"  # Management UI
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=admin
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - microservices

  # Prometheus Monitoring
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    networks:
      - microservices

  # Grafana Dashboard
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - prometheus
    networks:
      - microservices

  # Redis Cache
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - microservices

networks:
  microservices:
    driver: bridge

volumes:
  kong-db-data:
  user-db-data:
  order-db-data:
  mongo-data:
  rabbitmq-data:
  prometheus-data:
  grafana-data:
  redis-data:

การจัดการ Microservices:

# รันทั้งระบบ
docker compose -f docker-compose.microservices.yml up -d

# ตรวจสอบ services
docker compose ps

# Scale specific service
docker compose -f docker-compose.microservices.yml up -d --scale user-service=3

# ดู logs ของ service เฉพาะ
docker compose logs -f user-service

# รีสตาร์ท service
docker compose restart order-service

# ดูการใช้ทรัพยากร
docker stats

# หยุดเฉพาะ service
docker compose stop payment-service

# ลบทั้งหมด
docker compose down -v

ตัวอย่างที่ 5: Development Environment with Multiple Tools

version: '3.8'

services:
  # Main Application
  app:
    build: .
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "3000:3000"
    depends_on:
      - postgres
      - redis
      - elasticsearch
    networks:
      - dev-network

  # PostgreSQL Database
  postgres:
    image: postgres:15-alpine
    environment:
      - POSTGRES_PASSWORD=devpassword
      - POSTGRES_DB=devdb
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - dev-network

  # Redis Cache
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    networks:
      - dev-network

  # Elasticsearch
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data
    networks:
      - dev-network

  # Kibana
  kibana:
    image: docker.elastic.co/kibana/kibana:8.11.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
    networks:
      - dev-network

  # MailHog (Email testing)
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"  # SMTP
      - "8025:8025"  # Web UI
    networks:
      - dev-network

  # MinIO (S3-compatible storage)
  minio:
    image: minio/minio
    command: server /data --console-address ":9001"
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      - MINIO_ROOT_USER=minioadmin
      - MINIO_ROOT_PASSWORD=minioadmin
    volumes:
      - minio-data:/data
    networks:
      - dev-network

networks:
  dev-network:
    driver: bridge

volumes:
  postgres-data:
  es-data:
  minio-data:

Best Practices

1. การจัดการ Environment Variables

# ใช้ .env file
services:
  web:
    env_file:
      - .env
      - .env.local

# หรือกำหนดค่า default
services:
  web:
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - PORT=${PORT:-3000}

ไฟล์ .env.example:

# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=changeme

# Application
NODE_ENV=development
PORT=3000
SECRET_KEY=your-secret-key

2. การใช้ Health Checks

services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
  
  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

3. การจัดการ Dependencies

services:
  web:
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

4. การใช้ Networks แยกส่วน

services:
  frontend:
    networks:
      - frontend-network
  
  backend:
    networks:
      - frontend-network
      - backend-network
  
  database:
    networks:
      - backend-network

networks:
  frontend-network:
    driver: bridge
  backend-network:
    driver: bridge
    internal: true  # ไม่สามารถเข้าถึงจากภายนอกได้

5. การใช้ Build Arguments

services:
  app:
    build:
      context: .
      args:
        - NODE_VERSION=18
        - BUILD_DATE=${BUILD_DATE}
        - VERSION=${VERSION}

ใน Dockerfile:

ARG NODE_VERSION=16
FROM node:${NODE_VERSION}-alpine

ARG BUILD_DATE
ARG VERSION
LABEL build_date="${BUILD_DATE}"
LABEL version="${VERSION}"

6. การจำกัดทรัพยากร

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

7. Logging Configuration

services:
  web:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

8. การใช้ Secrets (Docker Swarm)

services:
  web:
    secrets:
      - db_password
      - api_key

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    external: true

9. Multi-stage Dockerfile

# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

10. การใช้ .dockerignore

node_modules
npm-debug.log
.git
.gitignore
.env
.env.local
README.md
.DS_Store
*.md
.vscode
.idea
coverage
.nyc_output
dist
build

คำสั่งเพิ่มเติมที่มีประโยชน์

การ Debug

# ดูการใช้ resources
docker compose top

# ดูข้อมูลของ service
docker compose inspect web

# ดู network configuration
docker network inspect <network-name>

# ดู volume information
docker volume inspect <volume-name>

# Export logs to file
docker compose logs > logs.txt

การ Backup และ Restore

# Backup database
docker compose exec db pg_dump -U postgres mydb > backup.sql

# Backup volume
docker run --rm -v myapp_db-data:/data -v $(pwd):/backup \
  alpine tar czf /backup/db-backup.tar.gz /data

# Restore database
docker compose exec -T db psql -U postgres mydb < backup.sql

# Restore volume
docker run --rm -v myapp_db-data:/data -v $(pwd):/backup \
  alpine sh -c "cd /data && tar xzf /backup/db-backup.tar.gz --strip 1"

Performance Tuning

# ลบ unused resources
docker system prune -a --volumes

# ดู disk usage
docker system df

# Clean up everything
docker compose down -v --rmi all --remove-orphans
docker system prune -a --volumes -f

สรุป

Docker Compose เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการ multi-container applications ช่วยให้การพัฒนา testing และ deployment ทำได้ง่ายและรวดเร็วขึ้น

Key Takeaways:

Resources เพิ่มเติม:


Happy Dockerizing! 🐳