0
0
Lập trình
Admin Team
Admin Teamtechmely

🚀 Xây Dựng & Vận Hành Nhiều Dịch Vụ với Docker Compose

Đăng vào 7 tháng trước

• 5 phút đọc

🚀 Xây Dựng & Vận Hành Nhiều Dịch Vụ với Docker Compose

📖 Tại Sao Nên Sử Dụng Docker Compose?

Khi bạn có nhiều microservices—chẳng hạn như một API Spring Boot, một frontend Node.js và một cơ sở dữ liệu PostgreSQL—việc xây dựng và khởi động các container một cách thủ công sẽ trở nên phức tạp. Docker Compose giúp giải quyết vấn đề này bằng cách cho phép bạn:

  • Định nghĩa tất cả dịch vụ trong một tệp (docker-compose.yml)
  • Tự động xây dựng hình ảnh từ các Dockerfile cục bộ
  • Tạo một mạng chia sẻ để các container có thể giao tiếp với nhau thông qua tên
  • Mở rộng và điều phối chúng với một lệnh duy nhất

🏗️ Cấu Trúc Dự Án

Dưới đây là một bố trí mở rộng cho hai dịch vụ Java và một cơ sở dữ liệu:

Copy
multi-service-app/
├─ service-a/
│  ├─ src/...
│  ├─ Dockerfile
│  └─ pom.xml
├─ service-b/
│  ├─ src/...
│  ├─ Dockerfile
│  └─ pom.xml
├─ database/
│  └─ init.sql
├─ .env
└─ docker-compose.yml

Mỗi dịch vụ độc lập, với Dockerfile và các sản phẩm xây dựng riêng.


🐳 Bước 1: Viết Dockerfile cho Dịch Vụ

Ví dụ về service-a/Dockerfile (Spring Boot JAR):

Copy
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY target/service-a.jar app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Lặp lại tương tự cho service-b.

Mẹo

  • Sử dụng tệp .dockerignore để bỏ qua target/ hoặc node_modules/ nhằm tăng tốc độ xây dựng.
  • Ghi chú hình ảnh cơ sở của bạn với một thẻ cụ thể để đảm bảo tính khả reproducibility.

⚙️ Bước 2: Tạo Tệp .env

Tập trung các biến môi trường:

Copy
POSTGRES_USER=myuser
POSTGRES_PASSWORD=secret
POSTGRES_DB=mydb
SPRING_PROFILES_ACTIVE=prod

Docker Compose sẽ tự động tải tệp này.


📝 Bước 3: Tệp docker-compose.yml

Dưới đây là một tệp Compose chất lượng sản xuất mà:

  • Xây dựng cả hai microservices từ mã nguồn
  • Khởi động một cơ sở dữ liệu PostgreSQL
  • Gán tên container rõ ràng
  • Tạo một mạng cầu nối dành riêng
  • Cấu hình kiểm tra sức khỏe và chính sách khởi động lại
Copy
version: "3.9"

networks:
  app-net:
    driver: bridge

volumes:
  db-data:

services:
  service-a:
    container_name: service-a-container
    build:
      context: ./service-a
      dockerfile: Dockerfile
    image: myorg/service-a:latest
    ports:
      - "8081:8080"
    networks:
      - app-net
    environment:
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
      DB_URL: jdbc:postgresql://db:5432/${POSTGRES_DB}
      DB_USER: ${POSTGRES_USER}
      DB_PASS: ${POSTGRES_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 5

  service-b:
    container_name: service-b-container
    build:
      context: ./service-b
      dockerfile: Dockerfile
    image: myorg/service-b:latest
    ports:
      - "8082:8080"
    networks:
      - app-net
    environment:
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
      SERVICE_A_URL: http://service-a:8080
    depends_on:
      service-a:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 5

  db:
    container_name: postgres-container
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "5432:5432"
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - app-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

🔑 Điểm Nổi Bật

  • Mạng: app-net giúp mỗi dịch vụ có một tên máy chủ tương ứng với khóa dịch vụ của nó (ví dụ: db, service-a).
  • Volumes: db-data lưu trữ dữ liệu cơ sở dữ liệu giữa các lần khởi động lại container.
  • depends_on với healthcheck đảm bảo các dịch vụ phụ thuộc chờ cho đến khi cơ sở dữ liệu hoặc các dịch vụ khác khỏe mạnh.
  • Môi trường: được lấy từ .env để quản lý bí mật dễ dàng hơn.

▶️ Bước 4: Xây Dựng và Khởi Động

Từ thư mục gốc của dự án:

Copy
docker compose up --build -d

Điều này sẽ:

  1. Xây dựng hình ảnh myorg/service-amyorg/service-b.
  2. Khởi động ba container (service-a-container, service-b-container, postgres-container).
  3. Kết nối chúng vào mạng app-net.

Kiểm tra mọi thứ đang chạy:

Copy
docker ps
docker compose logs -f

🔗 Giao Tiếp Giữa Các Dịch Vụ

Bên trong app-net:

  • service-b có thể gọi service-a tại http://service-a:8080
  • Cả hai dịch vụ kết nối với Postgres tại jdbc:postgresql://db:5432/mydb

DNS nội bộ của Docker có nghĩa là không cần địa chỉ IP cứng.


🛠️ Các Lệnh Quản Lý Vòng Đời Hữu Ích

Hành động Lệnh
Dừng các container docker compose stop
Khởi động lại với mã mới docker compose up --build -d
Dọn dẹp mọi thứ docker compose down
Xóa hình ảnh cũng vậy docker compose down --rmi all
Xem nhật ký container docker compose logs -f service-a
Mở rộng một dịch vụ (ví dụ: service-b) docker compose up -d --scale service-b=3

🧰 Thực Hành Tốt Nhất & Mẹo Chuyên Nghiệp

  1. Xây Dựng Nhiều Giai Đoạn:
    Biên dịch trong một hình ảnh builder, chỉ sao chép sản phẩm cuối cùng vào một hình ảnh runtime nhỏ hơn để có hình ảnh nhỏ hơn.

  2. Quản Lý Bí Mật:
    Đối với sản xuất, sử dụng bí mật Docker hoặc một kho lưu trữ thay vì .env thông thường.

  3. Giám Sát & Thống Kê:
    Tích hợp Prometheus/Grafana bằng cách thêm dịch vụ vào cùng một mạng.

  4. Tích Hợp CI/CD:
    Sử dụng docker compose build trong pipeline để tạo hình ảnh có phiên bản và đẩy chúng lên một registry.

  5. Giới Hạn Tài Nguyên:
    Thêm deploy.resources.limits để kiểm soát việc sử dụng CPU và bộ nhớ trong Swarm hoặc Compose v3+.


✅ Tóm Tắt

Với thiết lập này, bạn có thể:

  • Định nghĩa, xây dựng và chạy nhiều microservices và một cơ sở dữ liệu chỉ với một lệnh.
  • Gán mỗi container một tên sạch, mạng riêng biệt và kiểm tra sức khỏe.
  • Mở rộng theo chiều ngang và quản lý cấu hình môi trường một cách liền mạch.

Đây là một giải pháp chất lượng sản xuất để khởi động kiến trúc microservice của bạn với Docker Compose.
Chỉ cần thêm nhiều dịch vụ, sao chép mẫu và ngăn xếp của bạn sẽ phát triển một cách sạch sẽ và đáng tin cậy.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào