Bắt đầu với Docker – Phần 8: Tích hợp Docker trong CI/CD pipelines
Ở các phần trước, chúng ta đã làm quen với Docker, từ việc viết Dockerfile, build image, chạy container cho đến quản lý service bằng Docker Compose. Nhưng trong thực tế, Docker không chỉ được dùng trên máy cá nhân của lập trình viên. Một trong những nơi Docker phát huy sức mạnh rõ rệt nhất chính là trong CI/CD pipelines.
Nói đơn giản, CI/CD là quy trình tự động hóa việc kiểm tra, build và triển khai ứng dụng. Thay vì mỗi lần code xong lại tự tay chạy test, build project, copy file lên server rồi restart service, chúng ta để pipeline làm những việc đó. Docker giúp quy trình này ổn định hơn vì ứng dụng được đóng gói cùng môi trường chạy của nó.
Vì sao nên dùng Docker trong CI/CD?
Vấn đề quen thuộc của nhiều team là: “Máy em chạy được mà server không chạy được”. Nguyên nhân thường đến từ khác biệt về phiên bản Node.js, Python, Java, thư viện hệ thống hoặc biến môi trường. Docker giải quyết vấn đề này bằng cách đóng gói ứng dụng vào một image cố định.
Khi đưa Docker vào CI/CD, pipeline có thể thực hiện các bước như:
docker build -t my-app .
docker run my-app npm test
docker push registry.example.com/my-app:latest
Điểm hay là cùng một image có thể được dùng qua nhiều môi trường: development, staging và production. Điều này giúp giảm lỗi phát sinh do môi trường không đồng nhất.
Một pipeline Docker thường gồm những bước nào?
Một CI/CD pipeline tích hợp Docker thường bắt đầu khi lập trình viên push code lên Git. Sau đó hệ thống CI như GitHub Actions, GitLab CI, Jenkins hoặc CircleCI sẽ tự động chạy pipeline.
Quy trình phổ biến có thể như sau:
- Checkout source code
Pipeline lấy code mới nhất từ repository. - Build Docker image
Hệ thống dùngDockerfileđể tạo image cho ứng dụng. - Run test trong container
Thay vì chạy test trực tiếp trên máy CI, ta chạy test bên trong container để đảm bảo môi trường giống thực tế. -
Tag image
Image thường được gắn tag theo commit hash, version hoặc branch name. Ví dụ:docker tag my-app my-registry/my-app:v1.0.0 - Push image lên registry
Image được đẩy lên Docker Hub, GitHub Container Registry, GitLab Container Registry hoặc registry nội bộ. - Deploy
Server hoặc nền tảng triển khai sẽ pull image mới và chạy container mới.
Ví dụ với GitHub Actions
Một workflow đơn giản có thể trông như sau:
name: Docker CI
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t my-app .
- name: Run tests
run: docker run my-app npm test
Ví dụ trên chưa push image lên registry, nhưng nó cho thấy ý tưởng cơ bản: mỗi khi có code mới trên nhánh main, pipeline sẽ tự động build image và chạy test. Nếu test lỗi, pipeline dừng lại và team biết ngay code mới có vấn đề.
Khi dự án lớn hơn, ta có thể thêm bước đăng nhập registry và push image:
- name: Login to Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Push image
run: |
docker tag my-app myusername/my-app:latest
docker push myusername/my-app:latest
Thông tin nhạy cảm như username, password, token không nên ghi trực tiếp trong file pipeline. Thay vào đó, ta lưu trong phần Secrets của hệ thống CI/CD.
Một vài lưu ý thực tế
Khi dùng Docker trong CI/CD, đừng chỉ nghĩ đến việc “build được là xong”. Image nên được tối ưu để nhẹ, build nhanh và an toàn. Một số thói quen tốt gồm:
- Dùng
.dockerignoređể tránh copy những file không cần thiết vào image. - Không lưu password, API key hoặc token trong Dockerfile.
- Sử dụng tag rõ ràng thay vì chỉ phụ thuộc vào
latest. - Tách bước build và runtime nếu cần, ví dụ dùng multi-stage build.
- Chạy test trước khi push image lên registry.
- Scan image để phát hiện lỗ hổng bảo mật nếu dự án yêu cầu nghiêm túc.
Ví dụ, với ứng dụng Node.js, ta không nên copy cả thư mục node_modules từ máy local vào image. Thay vào đó, để container tự cài dependency dựa trên package-lock.json hoặc yarn.lock. Cách này giúp image sạch hơn và dễ tái tạo hơn.
Kết luận
Docker và CI/CD là một cặp rất hợp nhau. Docker giúp đóng gói ứng dụng thành một đơn vị nhất quán, còn CI/CD giúp tự động hóa quá trình kiểm tra, build và triển khai. Khi kết hợp lại, chúng ta có một quy trình phát triển phần mềm nhanh hơn, ít lỗi hơn và dễ mở rộng hơn.
Ở giai đoạn mới bắt đầu, bạn không cần xây dựng một pipeline quá phức tạp. Chỉ cần bắt đầu với ba bước cơ bản: build image, chạy test, push image. Khi team và sản phẩm lớn dần, bạn có thể bổ sung thêm các bước như scan bảo mật, deploy staging, approval thủ công hoặc rollback tự động.
Docker trong CI/CD không phải là thứ “cao siêu”, mà là một cách làm rất thực tế để biến quy trình triển khai từ thủ công, dễ sai sót thành tự động, rõ ràng và đáng tin cậy hơn.
- Bắt đầu với Docker – Phần 7: Triển khai ứng dụng web bằng Docker
- Giải quyết bài hiệu năng của Web Services sử dụng mô hình mạng hàng đợi và phân tích hồi quy Gaussian
- Analyze Data.
- Activities for Quantitative Test Process Control
- Bắt đầu với Docker – Phần 6: Tự động hóa triển khai với Docker Compose