DevOps Docker CI/CD GitHub Actions cho Web Developer Việt 2026

6 tháng trước · 9 phút đọc
Tại sao dev Việt cần biết Docker và CI/CD ngay bây giờ?
Bạn có bao giờ deploy xong local chạy ngon, lên server lại crash? Hoặc cả team 5 người mà môi trường mỗi người một kiểu, merge code là cầu nguyện?
Đó là vấn đề mà Docker và CI/CD sinh ra để giải quyết. Không phải chỉ cho big tech - mà cho bất kỳ team nào muốn ship code nhanh và ít bug hơn.
Vòng lặp deploy thủ công tốn thời gian hơn bạn nghĩ
Theo khảo sát {{fact:fact_0}}, các team áp dụng CI/CD giảm thời gian deploy trung bình xuống còn dưới 10 phút so với quy trình thủ công. Với GitHub Actions hiện tại cho {{fact:fact_1}} free minutes mỗi tháng cho public repo, barrier to entry gần như bằng 0.
Bài này mình sẽ đi từ Dockerfile cho Next.js 16, qua pipeline GitHub Actions, đến cách quản lý secrets trong team - không lý thuyết dài dòng, thẳng vào code chạy được.
Dockerfile cho Next.js 16: multi-stage build thực tế
Build Docker image "naive" cho Next.js có thể lên tới 1.2GB. Với multi-stage build, con số đó rút xuống còn khoảng 120MB. Không phải magic - chỉ là bỏ đi mọi thứ không cần thiết lúc runtime.
Logic đơn giản: stage builder cài đủ deps + build ra .next/standalone, stage runner chỉ copy output đó vào và chạy. Node modules, source code, cache - tất cả bị bỏ lại.
120MB thay vì 1.2GB - 10x nhỏ hơn nhờ multi-stage
Một điểm hay ho: copy package.json và pnpm-lock.yaml trước khi copy source code. Khi bạn chỉ sửa code mà không đổi deps, Docker sẽ dùng lại layer cache pnpm install - tiết kiệm vài phút mỗi build.
Trong next.config.js, cần bật standalone mode:
Trade-off cần biết: Standalone mode copy cả node_modules cần thiết vào output, nên lần đầu build vẫn lâu. Dùng BuildKit cache mount để tăng tốc:
Thêm .dockerignore để tránh copy rác vào build context:
node_modules
.next
.git
*.log
.env.local
Không có .dockerignore thì COPY . . sẽ copy cả node_modules vào context - chậm và thừa.
GitHub Actions pipeline: deploy Vercel và AWS ECS
Có Dockerfile rồi, bước tiếp là tự động hóa. Mình sẽ show 2 pipeline phổ biến nhất: Vercel cho frontend nhanh, AWS ECS cho production cần control hơn.
Deploy Vercel với GitHub Actions
Vercel có GitHub App integration tự động tạo preview URL khi bạn push PR. Nhưng nếu muốn control flow deploy (ví dụ: chỉ deploy sau khi test pass), dùng Actions manually:
PR tạo preview URL tự động, merge lên main thì production deploy
Deploy AWS ECS với Docker
Với AWS, flow sẽ là: build Docker image → push lên ECR → update ECS task definition → deploy. Điểm quan trọng là dùng OIDC thay vì lưu AWS access key trong secrets - an toàn hơn nhiều:
Dùng github.sha làm tag thay vì latest - khi cần rollback biết chính xác version nào đang chạy. latest là anti-pattern trong production.
Tối ưu build time với cache-from: type=gha: GitHub Actions cache Docker layers giữa các run. Build đầu tiên vẫn lâu, từ lần 2 trở đi nhanh hơn đáng kể vì chỉ rebuild layer thay đổi.
Monorepo với Turborepo: cấu trúc cho team Việt
Monorepo không có nghĩa là gộp mọi thứ vào một repo lộn xộn. Làm đúng thì bạn có shared components, shared config, và build chỉ compile những gì thay đổi - không build lại toàn bộ.
Turborepo là lựa chọn thực tế nhất cho team Việt: open source, tích hợp tốt với pnpm workspaces, và không cần trả tiền như Nx enterprise.
Cấu trúc thư mục
monorepo/
├── apps/
│ ├── web/ # Next.js - frontend chính
│ └── api/ # Express/Fastify - backend
├── packages/
│ ├── ui/ # Shared components (Button, Modal...)
│ └── config/ # ESLint, TSConfig dùng chung
├── turbo.json
├── pnpm-workspace.yaml
└── package.json
pnpm-workspace.yaml khai báo workspace:
turbo.json định nghĩa task dependencies:
dependsOn: ["^build"] có nghĩa: trước khi build apps/web, phải build xong packages/ui và packages/config. Turborepo tự xử lý dependency graph này.
Turborepo chỉ rebuild package nào thay đổi - không phải toàn bộ monorepo
GitHub Actions với monorepo
Trick hay: chỉ trigger deploy khi có thay đổi trong app tương ứng, dùng paths filter:
Với monorepo, build trong Actions cũng cần cache Turborepo:
--filter=web... (3 chấm) build web và tất cả packages mà web depend on. Không build api nếu không cần.
Mình từng thử Nx cho một dự án, overkill với team nhỏ. Turborepo đủ dùng cho 90% team Việt đang build startup.
Secrets management: đừng để lộ credentials của team
"Works on my machine" là joke quen thuộc. Nhưng "leaked credentials on GitHub" thì không ai cười được.
Mình thấy khá nhiều team Việt vẫn commit .env lên repo, hoặc share access key qua Zalo. Đó là rủi ro không đáng. Có 3 layer cần biết:
Layer 1: GitHub Secrets - đủ dùng cho hầu hết team
Vào Settings → Secrets and variables → Actions để thêm secrets. Trong workflow dùng ${{ secrets.TEN_SECRET }}.
Với AWS, đừng lưu access key. Dùng OIDC thay thế - AWS cấp token tạm thời cho mỗi workflow run:
Token tự hết hạn sau mỗi run. Không có long-lived credentials nào để leak.
Layer 2: Doppler - khi team cần centralized secrets
Doppler cho phép sync secrets từ một nơi ra nhiều môi trường (dev/staging/prod) và nhiều services. Tích hợp với Docker:
3 lớp secrets management - chọn theo quy mô team
Layer 3: AWS Secrets Manager - cho production nghiêm túc
App runtime cần credentials database, API keys? Lưu trong AWS Secrets Manager và fetch trong code:
Rotate secrets định kỳ: GitHub Secrets thì rotate theo quý. Nếu dùng Doppler hoặc AWS Secrets Manager thì có thể setup auto-rotation.
Quick checklist trước khi push code:
.envvà.env.localđã có trong.gitignore?- Không có hardcode API key trong source?
- Đã chạy
git log --all -S 'password'để check history chưa?
Nếu đã lỡ commit secret lên GitHub, xóa commit thôi chưa đủ - phải rotate key đó ngay lập tức vì GitHub scan history rất kỹ.
Tổng kết: bắt đầu từ đâu?
Mình biết đọc xong có thể overwhelmed - Docker, OIDC, Turborepo, Doppler... Nhưng không cần setup tất cả cùng một lúc.
Roadmap thực tế:
Tuần 1: Viết Dockerfile multi-stage cho project đang có. Build thử local, kiểm tra image size. Mục tiêu: dưới 200MB.
Tuần 2: Tạo workflow GitHub Actions đơn giản - chỉ chạy pnpm test khi có PR. Không cần deploy tự động ngay, quen flow đã.
Tuần 3: Kết nối workflow với Vercel deploy. Xóa access key cũ, chuyển sang OIDC nếu dùng AWS.
Tuần 4 trở đi: Nếu team lớn hơn 3 người, cân nhắc monorepo Turborepo và Doppler cho secrets.
4 tuần từ zero đến CI/CD - không cần học tất cả cùng lúc
Nếu bạn mới bắt đầu với DevOps và muốn có nền tảng vững hơn về Linux và terminal - thứ bắt buộc khi làm việc với Docker và server - khóa Làm việc với Terminal & Ubuntu cover đúng những gì bạn cần trước khi đi sâu vào phần này. Và nếu cần học Next.js trước khi containerize, khóa Frontend NextJS là điểm bắt đầu tốt.
Gặp vấn đề gì trong quá trình setup, drop comment - mình đọc hết.
