Docker Security: Best Practices bảo vệ Container

Photo of author

Văn Ngọc Tân

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

  1. Scan images trước mọi deploy — Dùng Docker Scout hoặc Trivy
  2. Pin version cụ thể — Không dùng latest
  3. Chạy non-root — Luôn tạo và dùng user không root
  4. Read-only filesystem — Trừ các thư mục cần ghi
  5. Giới hạn resources — Memory, CPU, processes
  6. Drop capabilities — Và add lại chỉ những gì cần
  7. Secrets outside image — Dùng Docker Secrets hoặc external env
  8. Minimal images — Alpine hoặc Distroless
  9. Network segmentation — Mỗi app một network
  10. 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

0 0 đánh giá
Đánh giá bài viết
Theo dõi
Thông báo của
guest
0 Góp ý
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Phản hồi nội tuyến
Xem tất cả bình luận