Docker đã trở thành standard cho việc deploy applications. Nhưng container không phải là sandbox — nếu cấu hình sai, attacker có thể thoát ra khỏi container và kiểm soát host. Bài viết này hướng dẫn các best practices để bảo mật Docker container từ image creation đến production deployment.

Tại sao Docker Security quan trọng?

Container chia sẻ kernel với host. Khác với VM, container không có hardware isolation mạnh. Một container bị compromise có thể:

  • Truy cập host filesystem.
  • Escalate privileges thành root.
  • Khai thác container runtime vulnerabilities.
  • Lan truyền sang containers khác.

Theo Palo Alto Networks, 94% container images có已知 vulnerabilities. Không phải vì Docker không bảo mật — mà vì người dùng không cấu hình đúng.

1. Image Security

Dùng Official Images

Official images trên Docker Hub được scan thường xuyên và maintain bởi Docker team.

# ✅ Tốt
FROM node:20-alpine

# ❌ Tránh
FROM some-random-user/node:latest

Dùng Minimal Base Images

Image càng nhỏ, attack surface càng ít. Alpine Linux chỉ ~5MB so với Ubuntu ~80MB.

# ✅ Tốt - Alpine
FROM node:20-alpine

# ✅ Tốt - Distroless
FROM gcr.io/distroless/nodejs20

# ❌ Tránh - Full OS
FROM ubuntu:22.04

Pin Image Versions

Không dùng latest — nó thay đổi theo thời gian, không predictable.

# ❌ Tránh - latest thay đổi
FROM node:latest

# ✅ Tốt - Pin version
FROM node:20.11.0-alpine3.19

# ✅ Tốt - Pin major version (auto update patch)
FROM node:20-alpine3.19

Scan Images trước khi deploy

# Docker Scout (built-in)
docker scout cves myapp:latest

# Trivy (open source)
docker run --rm aquasec/trivy image myapp:latest

# Hadolint (Dockerfile linting)
docker run --rm hadolint/hadolint Dockerfile

2. Dockerfile Best Practices

Không dùng Root User trong Container

Mặc định, container chạy với root. Tạo user riêng để giới hạn damage nếu bị compromise.

# Tạo non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Chuyển sang user
USER appuser

# Hoặc dùng numeric UID
RUN chown -R 1000:1000 /app

Copy chỉ những gì cần thiết

Không copy các file không cần thiết vào image — giảm kích thước và attack surface.

# ❌ Tránh - Copy toàn bộ project
COPY . /app

# ✅ Tốt - Chỉ copy cần thiết
COPY package*.json /app/
COPY src/ /app/src/
COPY dist/ /app/dist/

Dùng Multi-stage Builds

Build artifacts trong stage riêng, chỉ copy output vào final image. Không có compiler, build tools trong production image.

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./

# Chạy với non-root user
RUN chown -R 1000:1000 /app
USER 1000

CMD ["node", "dist/index.js"]

Health Check

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

3. Runtime Security (Docker Run)

Chạy với Non-Root

# Chạy container với user khác
docker run -u 1000 myapp:latest

# Hoặc dùng --user với username
docker run -u appuser myapp:latest

Read-only Root Filesystem

Ngăn container ghi vào filesystem — chỉ cho phép ghi vào volumes.

docker run --read-only myapp:latest

Giới hạn Capabilities

Linux capabilities cho phép fine-grained control. Drop all, chỉ add cái cần thiết.

# Drop all capabilities, chỉ add NET_BIND_SERVICE
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp:latest

# Nếu không cần any capability
docker run --cap-drop ALL myapp:latest

Seccomp Profile

Seccomp giới hạn syscalls mà container có thể thực hiện.

# Dùng default seccomp profile (block dangerous syscalls)
docker run --security-opt seccomp=profile.json myapp:latest

# Hoặc dùng unconfined (TRÁNH trong production)
docker run --security-opt seccomp=unconfined myapp:latest

AppArmor Profile

# Dùng AppArmor profile
docker run --security-opt apparmor=docker-default myapp:latest

No New Privileges

Ngăn container escalate privileges (setuid binaries).

docker run --security-opt=no-new-privileges:true myapp:latest

Resource Limits

# Giới hạn CPU và RAM
docker run \
  --memory="256m" \
  --memory-swap="256m" \
  --cpus="0.5" \
  --pids-limit=100 \
  myapp:latest

4. Network Security

Không map port ra ngoài nếu không cần

# ❌ Tránh - Map tất cả ports
docker run -P myapp:latest

# ✅ Tốt - Chỉ map port cần thiết
docker run -p 8080:3000 myapp:latest

Network Segmentation

# Tạo network riêng cho app
docker network create --driver bridge myapp-network

# Chạy container trong network riêng
docker run --network=myapp-network myapp:latest

# Database chỉ accessible từ app, không từ bên ngoài
docker run --network=myapp-network db:latest

Internal Network

# Database không có port mapped - chỉ accessible từ containers cùng network
docker run -d --network=myapp-network --name db postgres:16
# Không có -p 5432:5432

5. Secrets Management

Không bao giờ put secrets (passwords, API keys) trong Dockerfile hoặc environment variables plaintext.

# ❌ Tránh - Secrets trong ENV
ENV DATABASE_PASSWORD=secret123

# ❌ Tránh - Secrets trong CMD
CMD mysql -psecret123

# ✅ Tốt - Dùng Docker secrets (Swarm) hoặc external secrets
# Docker Secrets (Swarm mode)
echo "secret123" | docker secret create db_password -
docker service create --secret db_password myapp:latest

# ✅ Tốt - Dùng secret management service
# HashiCorp Vault, AWS Secrets Manager, Azure Key Vault

6. Logging và Monitoring

Docker Daemon Logging

# Configure log rotation
# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Container Logging

# Xem logs
docker logs mycontainer

# Xem logs real-time
docker logs -f mycontainer

# Export logs
docker logs mycontainer > app.log

Container Runtime Security (Falco)

Falco là runtime security tool, detect suspicious activities trong containers.

# Cài đặt Falco
apt install -y falco

# Hoặc chạy như container
docker run -d --name falco \
  --privileged \
  -v /var/run/docker.sock:/var/run/docker.sock \
  falcosecurity/falco:latest

7. Docker Bench Security

Docker Bench là script audit Docker host theo CIS benchmarks.

# Chạy Docker Bench
docker run -it --net host \
  --pid host \
  --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /var/lib:/var/lib \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /usr/lib/systemd:/usr/lib/systemd \
  -v /etc:/etc \
  aquasec/docker-bench:latest

Output sẽ show các security issues theo categories: Host Configuration, Docker Daemon Configuration, Container Images, Runtime Policies…

8. Docker Compose Security

# docker-compose.yml
version: "3.9"

services:
  app:
    image: myapp:latest
    user: "1000:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    resources:
      limits:
        cpus: '0.5'
        memory: 256M
    networks:
      - app-network
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

networks:
  app-network:
    driver: bridge

9. Security Checklist

  • [ ] Image: Dùng official images, pin versions.
  • [ ] Scan: Scan images với Trivy hoặc Docker Scout trước deploy.
  • [ ] User: Chạy container với non-root user.
  • [ ] Read-only: Mount filesystem read-only, chỉ allow writes to volumes.
  • [ ] Capabilities: Drop ALL capabilities, add only what needed.
  • [ ] Network: Dùng internal networks, không expose ports không cần.
  • [ ] Secrets: Không put secrets trong Dockerfile/ENV.
  • [ ] Resources: Set CPU/RAM limits.
  • [ ] Audit: Chạy Docker Bench định kỳ.

Kết Luận

Docker security không phải là setup once và quên. Đó là quy trình liên tục: scan images, update regularly, audit configs, monitor runtime.

  • Use minimal images (Alpine, Distroless).
  • Never run as root, drop capabilities.
  • Scan images before deploy.
  • Use secrets management, not ENV.
  • Monitor with Falco, audit with Docker Bench.

Kết hợp với SSH HardeningWireGuard VPN để có security stack hoàn chỉnh.

Chào các bạn mình là Quốc Hùng , mình sinh ra thuộc cung song tử ,song tử luôn khẳng định chính mình ,luôn luôn phấn đấu vượt lên phía trước ,mình sinh ra và lớn lên tại vùng đất võ cổ truyền ,đam mê của mình là coder ,ngày đi học tối về viết blog ...