Docker Swarm cơ bản: Hướng dẫn triển khai container cluster từ A đến Z

Vấn đề thực tế: Khi app chết theo server

Hồi đó mình đang deploy một dự án e-commerce nhỏ, chạy hoàn toàn bằng Docker trên một VPS duy nhất. Mọi thứ ổn cho đến khi server bị quá tải RAM — app bỗng dưng sập giữa đêm, không có gì tự restart. Tệ hơn là khi chuyển sang microservices, mình gặp memory leak trong container mà debug mất gần 2 ngày. Một phần vì không có cái nhìn tổng quan nào — không biết container nào đang ngốn tài nguyên bất thường trên host.

Thêm vào đó, mỗi lần traffic tăng đột biến, mình phải SSH vào server thủ công, docker run thêm container, rồi cấu hình lại nginx. Vừa tốn thời gian, vừa dễ nhầm lẫn.

Nghe quen không? Một server, scaling tay, không failover. Đó chính xác là lúc cần nghĩ đến container orchestration.

Phân tích nguyên nhân: Tại sao chỉ dùng Docker không đủ?

Docker rất tốt để đóng gói và chạy ứng dụng, nhưng nó không giải quyết được ba bài toán cốt lõi khi production:

  • Single point of failure: Một server chết, toàn bộ container chết theo.
  • Scaling thủ công: Muốn chạy 5 replica của một service, bạn phải tự docker run năm lần.
  • Không có load balancing tự động: Không có gì phân phối traffic giữa các container khi bạn chạy nhiều instance.

Bản chất của Docker là quản lý container trên một host duy nhất. Muốn nhiều máy làm việc cùng nhau — cần thêm một tầng orchestration ở trên.

Các cách giải quyết: Nên chọn gì?

Nhắc đến container orchestration, ba cái tên sẽ xuất hiện ngay:

  • Docker Swarm: Built-in trong Docker Engine, setup đơn giản, cú pháp quen thuộc, phù hợp team nhỏ hoặc dự án vừa.
  • Kubernetes (K8s): Mạnh mẽ nhất, nhưng learning curve cao và cần nhiều tài nguyên hơn để vận hành.
  • Nomad (HashiCorp): Linh hoạt, hỗ trợ cả workload non-container, nhưng ít phổ biến hơn hai cái kia.

Mới tiếp cận orchestration? Swarm là điểm khởi đầu hợp lý nhất: không cần cài thêm gì, vẫn dùng file docker-compose quen thuộc, và xử lý được 90% use case của dự án vừa và nhỏ.

Cách tốt nhất: Bắt đầu với Docker Swarm từng bước

Khái niệm cơ bản cần hiểu trước

Ba khái niệm bạn sẽ gặp xuyên suốt:

  • Node: Một máy chủ tham gia vào cluster. Có hai loại: manager (điều phối, ra quyết định) và worker (thực thi, chạy container).
  • Service: Một ứng dụng được deploy lên Swarm, định nghĩa image, số replica, port, resource limits…
  • Task: Một container đang thực tế chạy trên node. Mỗi replica của service là một task.

Bước 1: Khởi tạo Swarm cluster

Trên máy manager (server chính), chạy lệnh sau, thay 192.168.1.100 bằng IP thực của máy:

# Khởi tạo Swarm
docker swarm init --advertise-addr 192.168.1.100

Bạn sẽ thấy ngay lệnh để thêm worker vào cluster:

docker swarm join --token SWMTKN-1-xxxxx... 192.168.1.100:2377

Chạy lệnh đó trên máy worker là xong — node tự tham gia cluster ngay. Muốn lấy lại token sau này:

docker swarm join-token worker

Bước 2: Kiểm tra trạng thái cluster

# Xem danh sách node
docker node ls

# Kết quả mẫu:
# ID         HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS
# abc123 *   manager01   Ready     Active         Leader
# def456     worker01    Ready     Active

Bước 3: Deploy service đầu tiên

Thay vì docker run, bạn dùng docker service create:

# Deploy nginx với 3 replica, expose port 80
docker service create \
  --name my-nginx \
  --replicas 3 \
  --publish published=80,target=80 \
  nginx:alpine

# Xem service đang chạy
docker service ls
docker service ps my-nginx

Swarm tự động phân phối 3 container ra các node trong cluster và cân bằng tải giữa chúng.

Bước 4: Scale service chỉ với một lệnh

# Tăng từ 3 lên 5 replica
docker service scale my-nginx=5

# Hoặc dùng update
docker service update --replicas 5 my-nginx

Swarm tự động tìm node còn tài nguyên và spawn thêm container. Không cần tay, không cần SSH vào từng máy.

Bước 5: Deploy bằng Docker Stack (cách làm thực tế)

Trong production, bạn sẽ dùng Docker Stack — tương đương docker-compose nhưng chạy trên Swarm. Tạo file docker-stack.yml:

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
      update_config:
        parallelism: 1
        delay: 10s

  api:
    image: my-api:latest
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 512M
# Deploy stack lên Swarm
docker stack deploy -c docker-stack.yml my-app

# Xem các service trong stack
docker stack services my-app

# Xem log của service
docker service logs my-app_web

Bước 6: Rolling update không downtime

Đây là thứ mình dùng nhiều nhất trong production: update service mà không cần dừng app. Swarm update từng container một, đảm bảo luôn có instance đang chạy serve traffic:

docker service update \
  --image nginx:1.25-alpine \
  --update-parallelism 1 \
  --update-delay 10s \
  my-nginx

Bảo trì node không ảnh hưởng production

Trước khi bảo trì một worker, drain nó để Swarm chuyển task sang node khác:

# Chuyển node sang trạng thái drain (không nhận task mới, task cũ bị di chuyển)
docker node update --availability drain worker01

# Sau khi bảo trì xong, đưa node về active
docker node update --availability active worker01

Tips từ kinh nghiệm thực tế

Quay lại câu chuyện memory leak mình kể ở đầu — sau khi chuyển sang Swarm, mình tìm ra nguyên nhân nhanh hơn nhiều nhờ lệnh docker service ps my-app_api. Thấy ngay task nào bị restart liên tục, từ đó trace log container cụ thể đó. Nếu vẫn dùng Docker đơn lẻ, mình đã không có cái nhìn tổng quan như vậy.

Vài thứ mình học được — phần lớn từ sai lầm — khi vận hành Swarm thực tế:

  • Luôn set resource limits: resources.limits.memory trong stack file để tránh một service ăn hết RAM của cả node.
  • Manager node tối thiểu 3 cho production: Để đảm bảo quorum khi 1 manager bị lỗi (Swarm dùng Raft consensus).
  • Overlay network tự động: Các service trong cùng stack giao tiếp với nhau qua tên service, không cần cấu hình thêm gì.
  • Dùng Docker Secrets thay vì env plain text:
# Tạo secret
echo "my_db_password" | docker secret create db_password -

# Trong stack file:
# secrets:
#   db_password:
#     external: true

Tổng kết

Docker Swarm giải quyết được bài toán mà single-host Docker không làm được: high availability, auto-scaling và rolling update với downtime gần như bằng 0. Setup chỉ mất vài phút, và nếu bạn đã quen với docker-compose thì không cần học thêm nhiều.

Khi nào thì cần Kubernetes? Khi bạn thực sự cần autoscaling theo metrics, RBAC chi tiết, hay GitOps workflow phức tạp. Trước ngưỡng đó, Swarm đủ dùng — và đơn giản hơn nhiều.

Share: