Triển khai microservices bằng Docker Compose và Kubernetes trên dev
5 tháng 6, 2026
Giới thiệu về microservices
Microservices là kiến trúc phần mềm chia ứng dụng thành các dịch vụ nhỏ, độc lập, mỗi dịch vụ có thể phát triển, triển khai và mở rộng riêng biệt. Mỗi dịch vụ thường tương tác qua API hoặc message queue, giúp đội ngũ làm việc song song mà không gây xung đột. Khi phát triển web, việc tách biệt chức năng như xác thực, xử lý thanh toán, hoặc danh mục sản phẩm thành các microservices giúp hệ thống dễ bảo trì và mở rộng theo nhu cầu kinh doanh. Tuy nhiên, việc quản lý nhiều dịch vụ đồng thời cũng đặt ra thách thức về cấu hình môi trường, giám sát và triển khai. Để giảm bớt sự phức tạp trong giai đoạn phát triển, các đội thường sử dụng Docker Compose để mô phỏng toàn bộ stack trên máy local mà vẫn giữ được tính đồng nhất với môi trường production.
Pourquoi Docker Compose cho dev
Docker Compose cho phép định nghĩa các container, mạng và volume trong một tệp YAML duy nhất, từ đó người phát triển có thể khởi động tất cả dịch vụ bằng một lệnh duy nhất. Điều này giảm thiểu lỗi cấu hình hand‑made và đảm bảo mọi thành phần đều sử dụng cùng phiên bản image, môi trường biến môi trường và phụ thuộc. Ngoài ra, Compose hỗ trợ việc mở rộng dịch vụ (scale) và thay đổi cấu hình mà không cần chỉnh sửa từng Dockerfile riêng. Khi làm việc với microservices, việc có thể bắt đầu hoặc dừng một dịch vụ cụ thể mà không ảnh hưởng đến những dịch vụ khác rất hữu ích để debug và kiểm thử tích hợp. Đồng thời, Compose tích hợp tốt với các công cụ IDE và watchers để tự động rebuild image khi source code thay đổi, tạo ra quy trình lặp ráp.
Cấu trúc dự án
Một dự án microservices thường được tổ chức thành các thư mục con, mỗi thư mục tương ứng với một dịch vụ. Mỗi dịch vụ chứa source code, Dockerfile và éventuellement các tệp cấu hình riêng. Ở mức gốc dự án, chúng ta đặt tệp docker-compose.yml để mô tả toàn bộ hệ thống. Cấu trúc gợi ý:
- src/
- auth-service/
- src/
- Dockerfile
- package.json
- payment-service/
- src/
- Dockerfile
- package.json
- product-service/
- src/
- Dockerfile
- package.json
- auth-service/
- docker-compose.yml
Mỗi Dockerfile thường dựa trên image Node.js ufficiale, sao chép source, cài đặt dependencies và khai báo cổng listening. Việc giữ cấu trúc này đồng nhất giúp việc viết script build và deploy trở nên tự động hơn.
Docker Compose file
Dưới đây là ví dụ đơn giản của tệp docker-compose.yml để chạy ba dịch vụ auth, payment và product cùng với một mạng nội bộ và một volume cho database PostgreSQL dùng chung:
version: '3.8'
services:
auth:
build: ./src/auth-service
ports:
- '3001:3001'
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/auth
depends_on:
- db
payment:
build: ./src/payment-service
ports:
- '3002:3002'
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/payment
depends_on:
- db
product:
build: ./src/product-service
ports:
- '3003:3003'
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/product
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=microservices
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- '5432:5432'
volumes:
pgdata:
Trong file trên, mỗi service được build từ Dockerfile tương ứng, exposes cổng riêng và kết nối tới container db qua biến môi trường DATABASE_URL. Volume pgdata giữ dữ liệu giữa các lần restart để không mất thông tin trong quá trình dev.
Chạy local với Docker Compose
Sau khi có tệp docker-compose.yml,開發者 chỉ cần chạy:
docker compose up --build
Lệnh này sẽ xây dựng images ( nếu chưa có ) và khởi động tất cả containers. Để xem logs real‑time, có thể thêm flag -d để chạy trong background và sau đó sử dụng docker compose logs -f. Khi muốn dọn dẹp toàn bộ môi trường, dùng:
docker compose down -v
Lệnh này sẽ dừng containers, xóa network và loại bỏ volume đã được khai báo, giúp bắt đầu từ trạng thái sạch sẽ cho mỗi lần test mới.
Di chuyển sang Kubernetes
Khi dự án ổn định và cần kiểm thử trong môi trường gần giống production, việc chuyển sang Kubernetes cho phép mô phỏng khả năng mở rộng, tự động healing và load balancing. Thay vì chạy nhiều containers trên một host, Kubernetes sẽ phân phối chúng lên các node trong cluster. Để thực hiện việc này, chúng ta cần viết các manifest YAML cho Deployment, Service và éventuellement ConfigMap/Secret.
Tạo manifests K8s
Dưới đây là manifest Deployment cho dịch vụ auth (các dịch vụ khác tương tự):
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-deployment
labels:
app: auth
spec:
replicas: 2
selector:
matchLabels:
app: auth
template:
metadata:
labels:
app: auth
spec:
containers:
- name: auth
image: auth-service:latest
ports:
- containerPort: 3001
envFrom:
- secretRef:
name: auth-secret
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 5
periodSeconds: 10
Secret chứa các biến môi trường nhạy cảm như DATABASE_URL có thể được tạo bằng lệnh:
kubectl create secret generic auth-secret --from-literal=DATABASE_URL=postgres://postgres:password@postgres:5432/auth
Service để expose dịch vụ bên trong cluster:
apiVersion: v1
kind: Service
metadata:
name: auth-service
spec:
selector:
app: auth
ports:
- protocol: TCP
port: 3001
targetPort: 3001
type: ClusterIP
Tương tự, chúng ta tạo deployment và service cho payment và product. Để truy cập từ bên ngoài cluster trong môi trường dev, có thể sử dụng Ingress với đường dẫn dựa trên prefix hoặc sử dụng port‑forward tạm thời:
kubectl port-forward service/auth-service 3001:3001
CI/CD pipeline với GitHub Actions (optional)
Để tự động hóa quá trình build, test và deploy lên Kubernetes, 팀 có thể cấu hình workflow GitHub Actions. Dưới đây là một ví dụ đơn giản:
name: CI-CD
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push images
uses: docker/build-push-action@v4
with:
context: ./src/auth-service
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/auth-service:${{ github.sha }}
# Lặp lại cho payment và product
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Configure AWS EKS ( hoặc bất kỳ cluster nào )
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Update image trong deployment
run: |
kubectl set image deployment/auth-deployment auth=${{ secrets.DOCKERHUB_USERNAME }}/auth-service:${{ github.sha }}
kubectl set image deployment/payment-deployment payment=${{ secrets.DOCKERHUB_USERNAME }}/payment-service:${{ github.sha }}
kubectl set image deployment/product-deployment product=${{ secrets.DOCKERHUB_USERNAME }}/product-service:${{ github.sha }}
Workflow trên sẽ xây dựng image mới mỗi khi có push lên nhánh main, đẩy chúng lên Docker Hub và sau đó cập nhật image trong các deployment trên cluster EKS. Bạn có thể thay đổi provider cloud hoặc sử dụng kubectl trực tiếp nếu cluster đã được cấu hình sẵn.
Kết luận
Việc sử dụng Docker Compose trong môi trường development giúp팀 phát triển microservices nhanh chóng, đồng nhất và dễ dàng khôi phục trạng thái. Khi dự án đạt mức ổn định, việc chuyển sang Kubernetes cung cấp nền tảng mở rộng, tự động healing và khả năng kiểm thử tích hợp gần giống production. Kết hợp với CI/CD tự động qua GitHub Actions, 팀 có thể triển khai liên tục mà vẫn giữ được chất lượng và độ tin cậy. Hy vọng bài viết này đã cung cấp đủ thông tin thực tế để bạn bắt đầu xây dựng và quản lý hệ thống microservices của riêng mình.