Docker Compose cho lập trình viên Web: Môi trường phát triển chuẩn

✍️ Trần Minh Trí (Chuyên gia AI & Lập trình)
⏱️ 8 phút đọcIntermediate
#docker compose #docker #web development #container #devops
Docker Compose cho lập trình viên Web: Môi trường phát triển chuẩn

1. Docker Compose là gì và tại sao cần?

Docker Compose là công cụ định nghĩa và chạy nhiều container Docker cùng lúc. Thay vì chạy từng lệnh docker run riêng lẻ, bạn viết một file YAML duy nhất mô tả toàn bộ ứng dụng: web server, database, cache, queue.

Lợi ích chính:

  • Tái lập môi trường: Cả team dùng cùng cấu hình, không còn lỗi 'máy tôi chạy được'.
  • Một lệnh dừng: docker compose up khởi động mọi thứ.
  • Cách ly tốt: Mỗi service trong container riêng, không xung đột dependency.
  • Hot-reload: Mount code vào container, code thay đổi tự động cập nhật.
💡TIP
Nếu dự án của bạn cần 2+ services (web + database + cache), Docker Compose là bắt buộc.
📝NOTE
Docker Compose hiện là plugin của Docker CLI. Cài Docker Desktop hoặc docker compose plugin riêng.

2. File docker-compose.yml cơ bản

```yaml

version: '3.8'

services:

web:

build: .

ports:

- '3000:3000'

volumes:

- .:/app

- /app/node_modules

environment:

- NODE_ENV=development

- DATABASE_URL=postgres://user:***@db:5432/mydb

depends_on:

- db

db:

image: postgres:16-alpine

volumes:

- pgdata:/var/lib/postgresql/data

environment:

POSTGRES_USER: user

POSTGRES_PASSWORD: pass

POSTGRES_DB: mydb

ports:

- '5432:5432'

volumes:

pgdata:

```

Giải thích:

  • services: Danh sách các container.
  • build: Build từ Dockerfile trong thư mục hiện tại.
  • ports: Map port host:container.
  • volumes: Mount code vào container, giữ dữ liệu database.
  • depends_on: Database khởi động trước web.
  • environment: Biến môi trường cho mỗi service.

3. Network và giao tiếp giữa các service

Docker Compose tự động tạo một default network cho tất cả services. Mỗi service có thể gọi nhau qua tên service (DNS resolution).

Ví dụ: Web app kết nối database với URL postgres://user:***@db:5432/mydb. Docker tự động resolve db thành IP của container db.

Tạo nhiều network:

```yaml

services:

frontend:

networks:

- frontend

- backend

api:

networks:

- backend

database:

networks:

- backend

networks:

frontend:

backend:

```

Khi nào cần nhiều network? Khi frontend không cần truy cập trực tiếp database. Bảo mật hơn.

IMPORTANT
Không hardcode IP trong connection string. Luôn dùng service name. Để kiểm tra network: docker compose exec web ping db.

4. Volumes cho dữ liệu bền vững

Container mất dữ liệu khi restart. Volumes giải quyết vấn đề này.

Named volumes: Docker quản lý. Phù hợp cho database.

```yaml

volumes:

pgdata:

redisdata:

```

Bind mounts: Mount thư mục từ host. Phù hợp cho code hot-reload.

```yaml

volumes:

- ./src:/app/src # code thay đổi, container cập nhật ngay

- /app/node_modules # anonymous volume, giữ node_modules trong container

```

Mẹo: Dùng bind mount cho code để hot-reload hoạt động. Dùng named volume cho database để dữ liệu không mất khi docker compose down.

⚠️WARNING
Trên Windows/Mac, bind mount có thể chậm hơn Linux do filesystem sharing. Dùng :delegated hoặc :cached suffix nếu cần: - .:/app:delegated.

5. Profiles và multi-environment

Docker Compose profiles cho phép bật/tắt services theo môi trường.

```yaml

services:

web:

image: myapp-web

db:

image: postgres:16

redis:

image: redis:7

profiles: ['cache']

mailhog:

image: mailhog/mailhog

profiles: ['dev', 'staging']

```

Chạy:

  • docker compose up -> chỉ web + db
  • docker compose --profile cache up -> web + db + redis
  • docker compose --profile dev up -> web + db + mailhog

Multi-file Compose:

```

docker-compose.yml # Base config

docker-compose.dev.yml # Dev overrides

docker-compose.prod.yml # Prod overrides

```

Chạy: docker compose -f docker-compose.yml -f docker-compose.dev.yml up

6. Health checks và restart policies

Health check: Docker kiểm tra service còn sống không.

```yaml

services:

db:

image: postgres:16

healthcheck:

test: ['CMD-SHELL', 'pg_isready -U user']

interval: 10s

timeout: 5s

retries: 5

web:

depends_on:

db:

condition: service_healthy

```

Restart policies:

  • no: Không tự restart (default).
  • always: Luôn restart nếu dừng.
  • on-failure: Chỉ restart khi lỗi.
  • unless-stopped: Restart trừ khi bị dừng thủ công.
💡TIP
Dùng condition: service_healthy thay vì depends_on đơn thuần. Đảm bảo database sẵn sàng trước khi web start.
📝NOTE
Health check yêu cầu command trả về exit code 0 (healthy) hoặc 1 (unhealthy).

7. Docker Compose commands hữu ích

Commands cốt lõi:

  • docker compose up -d - Khởi động services ở chế độ background.
  • docker compose down - Dừng và xoá containers, networks.
  • docker compose down -v - Xoá luôn volumes (cẩn thận, mất dữ liệu).
  • docker compose logs -f web - Xem log realtime của service web.
  • docker compose exec web bash - Mở shell trong container web.
  • docker compose ps - Xem trạng thái các services.
  • docker compose build --no-cache - Build lại không dùng cache.
  • docker compose pull - Kéo image mới nhất.
  • docker compose restart web - Restart một service.

Debugging:

  • docker compose logs --tail=50 - Xem 50 dòng log cuối.
  • docker compose top - Xem processes trong containers.
  • docker compose events - Xem events realtime.
⚠️WARNING
Luôn dùng docker compose down -v cẩn thận. Volume chứa dữ liệu database sẽ bị xoá vĩnh viễn.

🙋 Câu hỏi thường gặp

Docker Compose khác gì với Kubernetes?

Docker Compose dành cho single-host: chạy local dev, CI, staging nhỏ.

Kubernetes dành cho multi-host: production cluster, auto-scaling, self-healing. Compose đơn giản hơn nhiều.

Làm sao debug khi container không start?

(1) docker compose logs service_name.

(2) docker compose exec service_name sh nếu container đang chạy.

(3) docker compose run --rm service_name sh để start container tương tác.

(4) Kiểm tra port conflict: netstat -tulpn | grep PORT.

Nên dùng Docker Compose version nào?

Version 3.8 trở lên. File format 3.8 hỗ trợ đầy đủ: profiles, healthcheck, deploy config. Tránh version 2 cũ.


Kiến thức liên quan