
Bài 5: Tối ưu Docker image bằng multi-stage và distroless
Tách builder khỏi runtime, kiểm tra tương thích libc và native module; giảm thành phần không cần thiết mà không cam kết tỷ lệ dung lượng chưa đo.

Chọn driver theo phạm vi kết nối, dùng DNS mạng tự tạo và kiểm tra published port; phân biệt mạng Docker Swarm với mô hình CNI của Kubernetes.
Đối chiếu ngày 24/10/2026. Các nguồn ở cuối bài dùng để kiểm tra phiên bản và giới hạn. Ví dụ phải điều chỉnh theo hệ điều hành và ứng dụng; không phải báo cáo thử nghiệm trên mọi nền tảng.
Hệ thống mạng của Docker được xây dựng trên nền tảng Container Network Model (CNM) của Docker, triển khai trên các cơ chế Linux (sử dụng network namespaces, veth pairs và iptables). Docker có các driver bridge, host, overlay, macvlan, ipvlan và none:

Khi bạn cài Docker, hệ thống tự động sinh một dải mạng mặc định tên là bridge (thường là subnet 172.17.0.0/16). Tuy nhiên, trên môi trường Production, bạn nên ưu tiên mạng tự tạo thay cho default bridge khi cần DNS và phân nhóm service vì hai hạn chế nghiêm trọng:
Giải pháp: Luôn tạo User-defined Custom Bridge
# Tao mot network rieng biet voi subnet tuy chinh
docker network create \
--driver bridge \
--subnet 172.28.0.0/16 \
--gateway 172.28.0.1 \
corp_internal_net
Khi các container cùng tham gia vào một User-defined Network, Docker sẽ tự động kích hoạt một DNS Server nhúng tại địa chỉ 127.0.0.11:
docker run -d --name dns_target --network corp_internal_net nginx:alpine
docker run --rm --network corp_internal_net busybox:1.37 nslookup dns_target
Bên trong container app_api, DNS của Docker sẽ tự động dịch tên máy chủ db_server sang địa chỉ IP nội bộ tương ứng mà không cần phải gán IP tĩnh.
--network host): Bỏ qua toàn bộ NAT và bridge. Cổng mà ứng dụng lắng nghe trong container chính là cổng của máy chủ. Thích hợp cho các ứng dụng yêu cầu hiệu năng mạng tối đa (High Throughput, Low Latency) hoặc xử lý hàng chục nghìn cổng đồng thời mà không bị nghẽn bảng theo dõi kết nối iptables conntrack.--network none): Dành cho các container xử lý tính toán chuyên sâu (Batch Processing, mã hóa dữ liệu offline) hoàn toàn không cần kết nối mạng để giảm kết nối mạng, không thay thế các lớp bảo vệ khác.Khi ứng dụng mở rộng ra cụm nhiều máy chủ, Overlay Network sử dụng giao thức đóng gói VXLAN để tạo một mạng phẳng logic kết nối các container trên các Host khác nhau mà không cần cấu hình định tuyến phức tạp.
Macvlan phù hợp khi các thiết bị mạng truyền thống (Router, Switch phần cứng) cần nhìn thấy và giao tiếp bằng địa chỉ LAN; Docker IPAM ví dụ không tự xin lease DHCP doanh nghiệp:
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 direct_lan_net
Khi bạn khai báo cờ -p 8080:80, Docker tự động chèn các quy tắc vào chuỗi PREROUTING và DOCKER của iptables trên máy chủ Host. Điều này có nghĩa là lưu lượng gửi tới cổng 8080 sẽ được chuyển tiếp (DNAT) vào địa chỉ IP nội bộ của container.
Cảnh báo quản trị UFW: Trên Ubuntu, các quy tắc của Docker thường được thực thi trước các quy tắc UFW thông thường. Do đó, nếu bạn dùng -p 8080:80, cổng đó có thể mở ra Internet ngay cả khi bạn chưa chạy lệnh ufw allow. Để an toàn, hãy luôn gán IP cục bộ: -p 127.0.0.1:8080:80 nếu chỉ muốn truy cập qua reverse proxy.
Mô hình bảo mật nhiều tầng (Defense-in-depth) khuyến nghị chia ứng dụng thành các dải mạng độc lập:
docker network create frontend_net
docker network create --internal backend_net
# Gan API vao hai mang; database chi vao backend_net theo thiet ke.
# Khong publish cong database neu chi API can truy cap.
docker network inspect frontend_net
docker network inspect backend_net
Tách network giảm đường kết nối trực tiếp, không bảo đảm chống mọi truy cập nếu API, host hoặc routing sai. Kiểm tra thực tế từ từng service trước khi kết luận cô lập.
Firewall backend có thể khác giữa iptables và nftables; không sao chép DOCKER-USER sang nftables mà chưa đọc tài liệu tương ứng. Published port có thể vượt chính sách UFW thông thường. Bind loopback khi chỉ cần reverse proxy host và thử từ máy ngoài. Host networking chia sẻ namespace, không di chuyển riêng NIC vật lý vào container.

Đọc đúng tài liệu theo phiên bản. Địa chỉ, tên và đường dẫn trong ví dụ cần thay theo môi trường. Sơ đồ là khái niệm, không phải screenshot hay benchmark.
Lưu cấu hình và digest cũ, kiểm tra backup phục hồi được, xác nhận endpoint và log sau thay đổi. Rollback phải tính đến dữ liệu đã ghi mới; đổi image không tự phục hồi database.

Tách builder khỏi runtime, kiểm tra tương thích libc và native module; giảm thành phần không cần thiết mà không cam kết tỷ lệ dung lượng chưa đo.

Cài Docker Engine từ kho phù hợp, kiểm tra phiên bản và quyền truy cập; phân biệt lưu trữ containerd mới với overlay2 trên máy nâng cấp.

Tra trạng thái, đọc log, kiểm tra OOM và giới hạn tài nguyên; hiểu tác động của stop, restart và prune trước khi thao tác trên máy production.

Phân biệt tag và digest, save/load với export; chuẩn bị TLS, xác thực và quy trình garbage collection trước khi vận hành private registry.