Bạn có biết?
Theo báo cáo của Unit 42 (Palo Alto Networks), 80% container images chứa ít nhất một lỗ hổng bảo mật Known Common Vulnerabilities (KCVEs). Và trong số đó, 60% đã được patch nhưng không được cập nhật trong Docker Hub!
Bảo mật container không chỉ là chuyện của security team — nó bắt đầu từ cách bạn viết Dockerfile và cấu hình container hàng ngày.
Tại sao Docker Security quan trọng?
Container chia sẻ kernel với host — nếu container bị compromise, kẻ tấn công có thể thoát ra ngoài host và kiểm soát toàn bộ hệ thống:
- ✅ Container escape — thoát khỏi container sang host
- ✅ Privilege escalation — leo thang quyền từ user thường sang root
- ✅ Secret theft — đánh cắp API keys, passwords
- ✅ Cryptojacking — dùng tài nguyên để đào tiền ảo
Image Security
1. Chỉ dùng Official Images
Official images được Docker verify và scan thường xuyên:
# ✅ An toàn — Official image
FROM node:20-alpine
# ⚠️ Cẩn thận — Image không rõ nguồn gốc
# NOT RECOMMENDED: FROM random-user/mystery-image:latest
2. Pin version cụ thể
# ❌ Không ổn định — latest thay đổi theo thời gian
FROM node:latest
# ✅ Pin version cụ thể — tái tạo được, bảo mật
FROM node:20.11.5-alpine3.19
3. Scan image trước khi deploy
# Dùng Docker Scout (miễn phí)
$ docker scout cves myapp:latest
# Dùng Trivy (open source)
$ trivy image myapp:latest
# Dùng Docker Hub Vulnerability Scanning
# (tự động khi push lên Docker Hub)
4. Sử dụng Minimal Base Images
# Nặng — chứa đầy đủ packages
FROM ubuntu:22.04 # ~77MB
# Nhẹ — bỏ bớt packages không cần
FROM ubuntu:22.04-slim # ~40MB
# Siêu nhẹ — chỉ có runtime tối thiểu
FROM alpine:3.19 # ~7MB
# Bảo mật tối đa — không có shell
FROM gcr.io/distroless/static-debian12 # ~2MB
Container Runtime Security
1. Chạy với Non-root User
Mặc định container chạy với quyền root. Đây là rủi ro bảo mật nghiêm trọng:
# Tạo user không có quyền root trong Dockerfile
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Chuyển sang user này trước khi chạy app
USER appuser
CMD ["node", "index.js"]
# Hoặc chỉ định user khi chạy container
$ docker run -u 1000:1000 myapp:latest
2. Read-only Filesystem
Ngăn container ghi vào filesystem — trừ khi cần thiết:
# Chỉ đọc filesystem (trừ /tmp và /var)
$ docker run --read-only myapp:latest
# Cho phép ghi vào thư mục cụ thể
$ docker run --read-only \
-v /tmp/writable:/tmp \
myapp:latest
3. Drop ALL Capabilities
Linux capabilities cho phép container làm những việc nguy hiểm. Drop tất cả:
# Drop tất cả capabilities, thêm lại chỉ những gì cần
$ docker run --cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
myapp:latest
4. Disable Privilege Escalation
# Không cho phép leo thang quyền
$ docker run --security-opt=no-new-privileges=true \
myapp:latest
5. Seccomp Profile — Giới hạn syscalls
# Dùng Docker's default seccomp profile (block dangerous syscalls)
$ docker run --security-opt seccomp:default \
myapp:latest
# Hoặc tạo profile tùy chỉnh
$ docker run --security-opt seccomp:/path/to/profile.json \
myapp:latest
6. AppArmor Profile
# Áp dụng AppArmor profile
$ docker run --security-opt apparmor:profilename \
myapp:latest
Network Security
1. Không Expose không cần thiết
# ❌ Expose tất cả ports
EXPOSE
# ✅ Chỉ expose ports cần thiết
EXPOSE 3000 5432
2. Host Network — Chỉ khi cần thiết
# Tránh dùng --network host (nhưng hiệu năng cao nhất, ít cô lập)
# CHỉ dùng khi cần performance tối đa
3. Network Segmentation
# Tạo networks riêng biệt cho từng ứng dụng
$ docker network create frontend-net
$ docker network create backend-net
# Web app chỉ connects được tới backend-net
# Database chỉ listens trên backend-net
Secrets Management
1. KHÔNG lưu secrets trong Image
# ❌ KHÔNG BAO GIỜ làm thế này!
ENV API_SECRET=my-secret-api-key
ENV DB_PASSWORD=secret123
# ❌ Cũng không trong source code
const dbPassword = "secret123"
2. Docker Secrets (cho Swarm)
# Tạo secret
$ echo "my-password" | docker secret create db_password -
# Trong docker-compose.yml:
services:
db:
image: postgres:15
secrets:
- db_password
secrets:
db_password:
external: true
3. Environment Variables bên ngoài
# Truyền secrets khi chạy (từ CI/CD hoặc secret manager)
$ docker run -e DATABASE_URL="postgres://user:pass@host:5432/db" \
myapp:latest
4. Kubernetes Secrets hoặc Vault
Trong production, nên dùng Kubernetes Secrets hoặc HashiCorp Vault để quản lý secrets tập trung.
Resource Limits
Giới hạn CPU và Memory
# Giới hạn memory
$ docker run --memory=512m --memory-swap=512m myapp:latest
# Giới hạn CPU
$ docker run --cpus=1.5 myapp:latest
# Giới hạn cả hai
$ docker run --memory=512m --cpus=0.5 myapp:latest
Tại sao quan trọng? Ngăn container chiếm tài nguyên và gây DoS cho các container khác.
Regular Updates
Image cần được cập nhật thường xuyên để fix vulnerabilities:
# Tạo CI pipeline tự động scan và cập nhật
# 1. Scan image định kỳ (daily/weekly)
# 2. Alert nếu có CVEs mới
# 3. Rebuild và push phiên bản mới
# 4. Redeploy trong staging trước
# 5. Deploy production nếu tests pass
Security Checklist
| Loại | Checklist Item | Priority |
|---|---|---|
| Image | Pin version cụ thể | Cao |
| Image | Scan images trước khi deploy | Cao |
| Image | Minimal base image (Alpine/Distroless) | Trung bình |
| Runtime | Chạy non-root user | Cao |
| Runtime | Read-only filesystem | Cao |
| Runtime | Drop ALL capabilities | Trung bình |
| Runtime | Giới hạn memory/CPU | Cao |
| Network | Chỉ expose ports cần thiết | Cao |
| Secrets | Không lưu secrets trong image | Cao |
| Updates | Cập nhật image định kỳ | Cao |
Best Practices tổng hợp
- Scan images trước mọi deploy — Dùng Docker Scout hoặc Trivy
- Pin version cụ thể — Không dùng latest
- Chạy non-root — Luôn tạo và dùng user không root
- Read-only filesystem — Trừ các thư mục cần ghi
- Giới hạn resources — Memory, CPU, processes
- Drop capabilities — Và add lại chỉ những gì cần
- Secrets outside image — Dùng Docker Secrets hoặc external env
- Minimal images — Alpine hoặc Distroless
- Network segmentation — Mỗi app một network
- Update thường xuyên — CI pipeline tự động
Bước tiếp theo
Bạn đã nắm vững cách bảo vệ container! Tiếp theo, hãy tìm hiểu Docker Networking nâng cao — cách kết nối container qua nhiều hosts với Overlay network và Service Discovery.
👉 Đọc tiếp: Docker Networking nâng cao: Overlay và Service Discovery