Tự động hóa Build và Push Docker Image lên Registry với GitHub Actions
Hướng dẫn tự động hóa Build và Push Docker Image bằng GitHub Actions: GHCR, Docker Hub, Buildx, metadata tags, cache, multi-platform, secrets, SBOM, provenance và troubleshooting.
ShanverseCập nhật 10 phút đọc— lượt xemĐang tải lượt xem
Git
Docker
GitHub Actions
Luồng CI hoàn chỉnh
Mermaid
Loading diagram…
Nguyên tắc:
Pull Request: build/test nhưng không push Image release.
Push vào default branch: push tag branch và Git SHA.
Git tag như v1.4.2: push semantic version tags.
Production deploy bằng version hoặc digest, không phụ thuộc latest.
Build một lần, promote cùng digest qua các môi trường.
Bình luận
Chuẩn bị Repository
Cần có:
Dockerfile production nên:
Dùng multi-stage build.
Pin base Image ở mức phù hợp.
Không copy .env, token hoặc Git metadata.
Chạy process bằng non-root user.
Có OCI labels để truy vết source/version/revision.
.dockerignore tối thiểu:
Không ignore file thực sự cần cho build. Kiểm tra build local trước:
Chọn Registry
Tên Image điển hình:
GHCR thuận tiện khi source và Actions cùng ở GitHub vì workflow có thể dùng GITHUB_TOKEN. Docker Hub cần username cùng access token lưu trong Actions Secrets.
Workflow chuẩn để push lên GHCR
Tạo .github/workflows/container.yml:
Thay ghcr.io/acme/api bằng owner và package viết thường của bạn.
Giải thích từng Action
actions/checkout
Checkout source code theo commit kích hoạt workflow. Dùng default shallow checkout nếu không cần toàn bộ Git history; tăng fetch-depth chỉ khi versioning cần history/tag.
docker/setup-qemu-action
Cài emulation để builder có thể tạo architecture khác runner, ví dụ arm64 trên runner amd64. Emulation chậm hơn native builder; project lớn có thể dùng native runners theo matrix.
docker/setup-buildx-action
Tạo Buildx builder dùng BuildKit, hỗ trợ cache nâng cao, multi-platform, secret mount, SBOM và provenance.
docker/login-action
Login Registry mà không ghi token vào script. Với GHCR trong cùng repository, GITHUB_TOKEN thường đủ khi workflow có packages: write và package access được cấu hình đúng.
docker/metadata-action
Sinh tag và OCI labels nhất quán từ branch, Pull Request, semantic version và Git SHA. Không tự nối string tag ở nhiều step khác nhau.
docker/build-push-action
Build bằng BuildKit, sử dụng cache, tạo multi-arch manifest và chỉ push khi không phải Pull Request.
Quyền của GITHUB_TOKEN
Luôn khai báo tối thiểu:
Nếu workflow chỉ build/test và không push:
Package GHCR thuộc organization có thể cần:
Kết nối package với source repository.
Cho repository Actions access package.
Kiểm tra permission inheritance.
Kiểm tra organization Actions policy.
Không dùng Personal Access Token có quyền rộng nếu GITHUB_TOKEN giới hạn theo repository đã đủ.
Không push Image từ Pull Request không tin cậy
Workflow đặt:
và chỉ login khi không phải Pull Request. Điều này giảm nguy cơ fork PR dùng build script độc hại để truy cập credential.
PR vẫn nên build để phát hiện Dockerfile hỏng, nhưng không publish tag release.
Push lên Docker Hub
Tạo Actions Secrets:
Dùng access token, không dùng account password.
Thay step login:
Metadata:
Token CI chỉ cần quyền push repository liên quan. Production pull nên dùng token read-only khác.
Tag strategy đúng cách
Với Git tag v1.4.2, metadata có thể tạo:
Với push branch main:
Các tag branch/channel là mutable. Git SHA tag khó thay đổi hơn nhưng digest mới là content identity bất biến:
Lưu digest output thành release/deployment metadata. Khi promotion, dùng digest đã test thay vì build lại.
Có nên dùng latest?
latest không có ý nghĩa “mới nhất” đặc biệt ở runtime; nó chỉ là tag tên latest. Nếu cần:
Chỉ tạo latest cho stable semantic release.
Không tạo latest từ mọi branch.
Không dùng latest làm identity duy nhất của production.
Luôn giữ version và SHA tag song song.
Build cache với GitHub Actions cache
Cache hiệu quả khi Dockerfile sắp xếp layer đúng:
Không copy toàn source trước npm ci, vì mọi thay đổi code sẽ invalidate dependency layer.
Tách cache scope khi monorepo có nhiều Image:
Cache là tăng tốc, không phải artifact release. Pipeline phải build lại chính xác ngay cả khi cache miss.
Build secret an toàn
Không truyền secret bằng Docker ARG hoặc ENV.
Dockerfile:
Workflow:
Secret mount chỉ tồn tại trong build step. Không copy secret sang artifact hoặc echo trong log.
Kiểm thử trước khi push
Pipeline nên chạy unit/lint/integration test trước build release:
Có thể build một Image single-platform với load: true để smoke test local trên runner:
Buildx không thể load một multi-platform manifest vào classic local image store. Smoke test một platform, còn release step dùng --push multi-arch. Với yêu cầu build-once nghiêm ngặt, push vào staging registry theo digest, test digest đó rồi promote cùng artifact.
Multi-architecture Image
Cân nhắc:
Native modules phải build đúng target architecture.
Base Image phải hỗ trợ tất cả platforms.
QEMU chậm hơn native execution.
Test ít nhất một workload thật trên mỗi architecture production.
Kiểm tra:
Lỗi exec format error thường do architecture không khớp.
SBOM và provenance
SBOM mô tả package trong Image; provenance mô tả cách artifact được build. Chúng hỗ trợ audit và policy nhưng không thay thế vulnerability scan hoặc chữ ký.
Pipeline supply chain đầy đủ:
Tùy registry và chính sách, thêm Cosign/signing hoặc GitHub artifact attestation với quyền tối thiểu cần thiết. Không cấp id-token: write nếu không dùng OIDC/signing.
Action version và supply-chain security
Ví dụ dễ đọc dùng major tags như @v4, @v3, @v6. Với repository nhạy cảm:
Pin third-party Action bằng full commit SHA.
Dùng dependency update bot để cập nhật SHA.
Chỉ cho phép Actions từ publisher tin cậy.
Review release note trước nâng version.
Giới hạn permissions ở workflow/job.
Không chạy self-hosted runner chung với code không tin cậy.
Tối ưu workflow monorepo
Chỉ build khi file liên quan thay đổi:
Hoặc dùng matrix:
Mỗi service cần cache scope, Dockerfile và Image name riêng. Tránh để thay đổi frontend rebuild toàn bộ backend Images.
Tránh workflow chạy trùng
Phù hợp branch/PR vì chỉ cần commit mới nhất. Với release tag, cân nhắc không cancel job đang publish artifact để tránh manifest dở dang.
Promotion và deployment
Không để job build trực tiếp sửa production nếu chưa có approval. Tách:
Build workflow: tạo Image, test, scan và ghi digest.
Promotion workflow: gắn release metadata/tag vào digest đã duyệt.
Deploy workflow: cập nhật environment bằng digest, có approval và rollback.
Docker Compose production:
Deploy:
Lỗi thường gặp
permission_denied: write_package
Kiểm tra:
packages: write.
Package access cho repository.
Organization policy.
Đúng owner trong tên ghcr.io/owner/image.
repository name must be lowercase
Dùng Image name lowercase cố định thay vì truyền owner/repository có chữ hoa.
Workflow push Image trên Pull Request
Đặt push và login theo điều kiện event. Không cung cấp secret cho code fork.
Cache không hit
Kiểm tra cache scope, Dockerfile layer ordering, lockfile thay đổi, context có file timestamp/generated và quyền Actions cache.
Multi-arch build quá chậm
Giảm platform không dùng, tối ưu layer/cache, hoặc dùng native runner cho từng architecture rồi tạo manifest.
no matching manifest for linux/arm64
Base Image hoặc release manifest thiếu platform. Kiểm tra bằng imagetools inspect.
Image có tag nhưng production vẫn cũ
Tag mutable và node chưa pull. Dùng digest/version mới, docker compose pull, sau đó recreate service.
Checklist production
PR chỉ test/build, không push release Image.
Workflow permissions theo least privilege.
GHCR dùng repository-scoped GITHUB_TOKEN khi phù hợp.
Docker Hub dùng access token riêng, không dùng password.
Tag gồm version, Git SHA và branch/channel cần thiết.
Production lưu và deploy digest bất biến.
BuildKit cache được cấu hình và Dockerfile tối ưu layer.
Build secret dùng secret mount, không dùng ARG/ENV.
Multi-arch manifest chứa đúng platforms.
Unit/lint/smoke test chạy trước release/promotion.
SBOM, provenance, vulnerability scan và signing theo policy.
Third-party Actions được pin/review.
Không dùng pull_request_target với code không tin cậy.
Hướng dẫn Docker Hardening thực tế với non-root user, multi-stage builds, minimal image, read-only filesystem, Linux capabilities, seccomp, scanning và supply-chain security.
Docker Compose khi nào không còn đủ? So sánh Kubernetes và Docker Swarm về multi-host, self-healing, scaling, rolling update, networking, secrets và lộ trình migration production.
Hướng dẫn tự động deploy ứng dụng Docker lên VPS Ubuntu và cloud providers bằng GitHub Actions: AWS ECS/App Runner/EC2, Vercel, Render, secrets, healthcheck, rollback và zero-downtime strategy.