Developer push code
│
▼
GitLab nhận push
│
▼
Pipeline kích hoạt
(theo nhánh push)
│
├── develop-v2 → [deploy-develop] → Máy chủ Dev
├── staging-v2 → [deploy-staging] → Máy chủ Staging
├── release-v2 → [deploy-release] → Máy chủ Release
└── master-v2 → [build-master] → Build Docker image → AWS ECR
└── [deploy-master] → Máy chủ Production| Môi trường | Nhánh Git | Mục đích | Loại Deploy |
|---|---|---|---|
| Development | develop-v2 | Kiểm thử tính năng mới trong ngày | Deploy trực tiếp bằng docker compose |
| Staging | staging-v2 | Kiểm thử trước khi đưa lên Release | Deploy trực tiếp bằng docker compose |
| Release | release-v2 | Môi trường gần Production, test cuối | Deploy trực tiếp bằng docker compose |
| Production | master-v2 | Môi trường thật, phục vụ khách hàng | Build image → push AWS ECR → deploy từ ECR |
.gitlab-ci.yml| Biến | Giá trị | Ý nghĩa |
|---|---|---|
AWS_REGION | ap-southeast-1 | Vùng AWS (Singapore) |
AWS_ACCOUNT_ID | 211125536219 | ID tài khoản AWS |
AWS_ECR | {account}.dkr.ecr.{region}.amazonaws.com | Địa chỉ registry Docker trên AWS |
IMAGE_NAME | traffic/tool-v2-prod | Tên image trên ECR |
PLATFORM | linux/amd64 | Kiến trúc CPU target |
TAG_LATEST | {ECR}/{IMAGE}:latest | Tag phiên bản mới nhất |
TAG_COMMIT | {ECR}/{IMAGE}:{commit_hash} | Tag theo commit hash cụ thể |
Push lên nhánh → Pipeline kích hoạt job tương ứng
develop-v2 → deploy-develop
staging-v2 → deploy-staging
release-v2 → deploy-releaseStep 1: GitLab Runner khởi động job
│
▼
Step 2: Nạp SSH Key vào Agent
(Key được lưu dưới dạng Base64 trong GitLab CI Variables)
- Giải mã Base64 từ biến $TRAFFIC_DEV_KEY
- Đăng ký vào ssh-agent
- Cấu hình SSH bỏ qua kiểm tra host
│
▼
Step 3: SSH vào máy chủ Worker Target
(dùng IP và Port từ CI Variables)
│
▼
Step 4: [Trên máy chủ Worker] Kéo code mới nhất
- Kiểm tra thư mục dự án đã tồn tại chưa
- git pull origin — cập nhật repo wrapper
- cd build/tools && git checkout {branch} && git pull — cập nhật submodule mã nguồn chính
│
▼
Step 5: [Trên máy chủ Worker] Build và khởi động Docker
- docker compose up --build -d
- Docker đọc Dockerfile trong thư mục build/
- Build image từ mã nguồn mới nhất
- Khởi động container với cấu hình trong docker-compose.yml
│
▼
Step 6: Dọn dẹp image thừa
- docker image prune -f
- Xóa các image cũ không còn được sử dụng
│
▼
Pipeline kết thúc ✅Push lên master-v2
│
▼
Step 1: SSH vào máy Build Server (Bastion)
│
▼
Step 2: Đăng nhập AWS ECR
aws ecr get-login-password | docker login --username AWS --password-stdin {ECR}
│
▼
Step 3: Cập nhật mã nguồn
- git pull origin (cập nhật repo chính)
- git checkout master-v2 && git pull (cập nhật submodule)
│
▼
Step 4: Kéo image cũ về để dùng làm build cache
docker pull {ECR}/{IMAGE}:latest || true
(|| true: không dừng pipeline nếu chưa có image nào)
│
▼
Step 5: Build Docker image
docker buildx build \
--cache-from {TAG_LATEST} \ ← Dùng cache từ image cũ để tăng tốc
--platform linux/amd64 \ ← Chỉ định kiến trúc CPU
-t {TAG_LATEST} \ ← Gán tag :latest
-t {TAG_COMMIT} \ ← Gán tag theo commit hash
--push . ← Push thẳng lên AWS ECR
│
▼
Step 6: Dọn dẹp image local
docker image prune -f
│
▼
Image mới đã có trên AWS ECR ✅Sau khi build-master thành công
│
▼
Step 1: SSH vào từng máy chủ Production Worker
(Lặp qua danh sách IP trong $VNETWORK_TRAFFIC_PROD_IP)
│
▼
Step 2: Đăng nhập AWS ECR trên máy Production
aws ecr get-login-password | docker login --username AWS --password-stdin {ECR}
│
▼
Step 3: Kéo image mới nhất về máy Production
docker pull {ECR}/{IMAGE}:latest
│
▼
Step 4: Cập nhật file cấu hình
git pull origin (cập nhật docker-compose.yml và .env nếu có thay đổi)
│
▼
Step 5: Khởi động lại container với image mới
docker compose up -d --force-recreate --remove-orphans
- --force-recreate: buộc tạo lại container dù config không đổi
- --remove-orphans: xóa container cũ không còn trong compose file
│
▼
Step 6: Dọn dẹp image cũ
docker image prune -f
│
▼
Production cập nhật thành công ✅mongodb_data — đảm bảo không mất dữ liệu khi restart.| Loại biến | Ví dụ | Ghi chú |
|---|---|---|
| SSH Private Key | $TRAFFIC_DEV_77_37_47_88_KEY | Mã hóa Base64, giải mã khi cần |
| Thông tin SSH | $TRAFFIC_DEV_77_37_47_88_IP, _PORT, _USER | IP, port, username của máy chủ |
| AWS Credentials | Cấu hình qua IAM Role trên máy Build | Không lưu Access Key trực tiếp |
| Môi trường App | Được quản lý qua .env trên từng máy chủ | Không commit .env vào repo |
feature/xxx → develop-v2 → staging-v2 → release-v2 → master-v2
(phát (kiểm thử (test tích (kiểm thử (production
triển) hàng ngày) hợp) cuối cùng) thật)| Nhánh | Ai merge | Điều kiện merge |
|---|---|---|
develop-v2 | Developer | Sau khi code xong tính năng |
staging-v2 | Tech Lead | Sau khi dev xác nhận ổn |
release-v2 | Tech Lead / PM | Sau khi staging test xong |
master-v2 | System Admin | Sau khi release test xong và được duyệt |
| Tình huống | Nguyên nhân | Cách xử lý |
|---|---|---|
| Pipeline không kích hoạt | Push sai nhánh | Kiểm tra tên nhánh có đúng với only: trong gitlab-ci.yml |
| SSH connection failed | SSH key hết hạn hoặc sai | Cập nhật lại CI Variable chứa SSH key |
| docker build thất bại | Lỗi mã nguồn hoặc npm install fail | Xem log chi tiết trong job output trên GitLab |
| docker pull ECR thất bại | AWS credentials hết hạn hoặc wrong region | Kiểm tra lại IAM role hoặc AWS_REGION |
| Container không start | File .env thiếu biến | SSH vào máy, kiểm tra .env và docker compose logs |
| Image quá lớn | Không dọn dẹp layer Docker | Thêm .dockerignore, tối ưu Dockerfile layer |