DevOps 22/09/2026 5 phút

cgroups: giới hạn CPU và bộ nhớ container — và vì sao vượt RAM thì bị giết, vượt CPU chỉ chậm

namespace cô lập tầm nhìn; cgroup là nửa còn lại — giới hạn tài nguyên. Bài này chạy thật: --cpus 0.25 làm cùng workload chậm đúng 4 lần, giới hạn nằm trong file /sys/fs/cgroup (memory.max, cpu.max), và container vượt --memory 32m bị kernel OOM kill thật (OOMKilled=true, exit 137). Hai kiểu vượt khác nhau: RAM bị giết, CPU chỉ throttle.

DevOps 22/09/2026 5 phút

Image layers và overlayfs: vì sao 100 container cùng image không tốn 100 lần đĩa

Image Docker là chồng nhiều layer chỉ-đọc; container chỉ thêm một lớp ghi mỏng chồng lên. Bài này chạy thật: docker history phơi bày từng layer, tự dựng overlayfs để thấy copy-on-write (sửa file thì copy sang upper, lower giữ nguyên), và ba container cùng image mỗi cái chỉ thêm 4.1kB trong khi 67.9MB image dùng chung.

DevOps 22/09/2026 6 phút

Dockerfile cache: vì sao đổi một dòng code khiến build cài lại toàn bộ dependencies

Mỗi lệnh Dockerfile là một layer được cache; đổi một layer làm hỏng cache của MỌI layer sau nó. Đặt COPY . . trước khi cài dependencies là lỗi kinh điển: sửa một dòng code buộc build cài lại toàn bộ deps. Bài này đo thật hai Dockerfile cùng app: sau khi sửa code, bản sai mất 3.8s (cài lại deps), bản đúng chỉ 0.6s.

DevOps 22/09/2026 5 phút

Build context: vì sao docker build gửi cả thư mục lên daemon, và .dockerignore cứu bạn

Dấu chấm trong docker build . là build context — docker nén CẢ thư mục và gửi lên daemon trước khi build, kể cả file không dùng tới. Bài này đo thật: một thư mục 70MB (node_modules + .git) gửi nguyên context 70.01MB dù Dockerfile chỉ COPY app.py; thêm .dockerignore, context còn 4.096kB — và quan trọng hơn, nó chặn .env/.git lọt vào image.

DevOps 22/09/2026 5 phút

Multi-stage build: vì sao image Go của bạn nặng 400MB thay vì 3MB

Để BUILD một chương trình cần trình biên dịch và cả toolchain hàng trăm MB; để CHẠY chỉ cần binary vài MB. Nếu build và chạy cùng một image, image cuối mang theo cả toolchain. Bài này build một chương trình Go thật hai cách: một-stage cho image 407MB, multi-stage (copy binary sang scratch) cho 3.4MB — cùng chạy y hệt, giảm ~120 lần.

DevOps 22/09/2026 5 phút

Container networking: gọi nhau bằng tên, và vì sao mạng bridge mặc định không có DNS

Trong một mạng bridge tuỳ chỉnh, container gọi nhau bằng tên (Docker có DNS nội bộ); nhưng mạng bridge MẶC ĐỊNH thì không — gọi bằng tên báo bad address. Bài này chạy thật: container gọi nhau qua tên trên mạng riêng, lỗi trên mạng mặc định, và -p publish cổng để host vào được container (curl trả 200).