DevOps · Docker

Docker Production: Từ Development Đến Deploy Thực Tế

Docker Production - Từ development đến deploy thực tế

"It works on my machine" — câu nói kinh điển mà Docker sinh ra để giải quyết. Docker đóng gói app + dependencies thành container chạy giống nhau ở mọi nơi: laptop developer, staging server, hay production cluster. Theo Docker 2024 survey, 87% enterprises đã sử dụng containers trong production. Nhưng Docker cho development khác Docker cho production 180 độ: dev dùng volumes, hot-reload, debug ports mở rộng. Production cần: multi-stage builds (image nhỏ gọn), security hardening (non-root user), health checks (self-healing), resource limits (prevent OOM). Bài viết này là production checklist 10 điểm từ kinh nghiệm thực tế deploy BanhCuonFlow — mỗi điểm đều có giải thích tại sao quan trọng và cách thực hiện cụ thể.

Tại Sao Docker Development ≠ Docker Production?

Trong development: bạn mount source code bằng bind volumes để hot-reload, expose debug ports (5005, 9229), chạy as root cho tiện, không set resource limits, dùng docker-compose up và xong. Nếu deploy production với cùng config này: bạn sẽ gặp container chiếm hết RAM server (vì không giới hạn memory), security vulnerabilities (vì root user), image quá lớn (vì chứa cả build tools), và không tự recovery khi app crash (vì không health check). Docker official documentation khuyến cáo: "Production containers MUST be treated as immutable infrastructure" — build image 1 lần, cấu hình qua environment variables, không modify container sau khi deploy.

Production Checklist: 10 Điểm Bắt Buộc

① Multi-Stage Build

Stage 1 (build): chứa SDK, compiler, build tools — dùng để compile code, restore dependencies. Stage 2 (runtime): chỉ copy output từ stage 1, dùng base image nhỏ (alpine hoặc distroless). Kết quả: BanhCuonFlow .NET image từ 1.5GB (build stage) giảm xuống 200MB (runtime stage). Image nhỏ hơn = pull nhanh hơn khi deploy = ít CVE hơn vì ít packages cài đặt = attack surface nhỏ hơn đáng kể. Sử dụng BuildKit và cache mounts để tăng tốc build times lặp lại.

② Non-Root User

KHÔNG BAO GIỜ chạy container as root trong production. Nếu attacker compromise container chạy root → họ có full access đến filesystem, network, và có thể escape ra host system. Thêm USER appuser trong Dockerfile, tạo user với adduser --disabled-password. BanhCuonFlow: tất cả containers chạy non-root, file permissions restricted chỉ read cho app code, write chỉ cho logs và uploads directory cụ thể.

③ Health Checks

HEALTHCHECK CMD curl -f http://localhost/health || exit 1 — Docker dùng health check để biết container healthy không. Unhealthy → tự động restart (Docker Swarm) hoặc replace pod (Kubernetes). Health check nên verify application-level health, không chỉ process running: BanhCuonFlow /health endpoint kiểm tra DB connection, Redis connection, disk space — nếu bất kỳ thứ gì fail, endpoint trả 503 và container được restart. Configure: interval 30s, timeout 10s, start-period 60s (cho app warm up), retries 3.

④ Resource Limits

deploy: resources: limits: memory: 2G, cpus: '2'. Không set limits → 1 container memory leak có thể OOM kill toàn bộ server, ảnh hưởng tất cả containers khác trên cùng host. Luôn set cả --memory--memory-swap bằng nhau để disable swap — tránh latency spikes không dự đoán được. BanhCuonFlow production specs: API container 2GB RAM / 2 CPU, PostgreSQL 4GB / 2 CPU, Redis 512MB / 1 CPU. Monitor actual usage và điều chỉnh limits theo workload thực tế.

⑤ .dockerignore

File .dockerignore quan trọng ngang .gitignore. Exclude: .git, node_modules, test files, local env files, IDE configs, secrets. Không exclude → build context lớn → build chậm + risk leak sensitive data vào image (API keys trong .env files bị copy vào image layers, ai pull image đều đọc được).

⑥ Environment Variables, Không Hardcode

Database connection string, API keys, secrets → environment variables hoặc Docker secrets (encrypted at rest). KHÔNG hardcode trong Dockerfile hoặc source code — mọi thứ hardcoded trong image layer đều có thể extract bằng docker history. BanhCuonFlow: .env file cho Docker Compose, injected at runtime qua env_file directive, với file permissions 600 (chỉ owner đọc được).

⑦ Logging to stdout/stderr

Log ra console (stdout cho info, stderr cho errors), không log ra file trong container. Docker logging driver capture stdout → forward đến ELK Stack, Grafana Loki, CloudWatch, hoặc bất kỳ centralized logging system nào. Log files trong container = mất khi container restart, khó aggregate, tốn disk space. BanhCuonFlow dùng Serilog output console + JSON format để dễ parse bởi log aggregators.

⑧ Named Volumes cho Persistent Data

Database data, uploaded files → Docker named volumes, KHÔNG bind mounts. Named volumes managed by Docker engine, survive container recreate/upgrade. BanhCuonFlow: pgdata volume cho PostgreSQL data, uploads volume cho user files. Backup volumes định kỳ bằng docker run --volumes-from + tar/rsync.

⑨ Reverse Proxy (Nginx)

Nginx đứng trước app server làm reverse proxy: SSL/TLS termination (Let's Encrypt free certificates), static file serving (tránh load app server), rate limiting (prevent DDoS), request buffering, gzip compression. App server KHÔNG expose trực tiếp internet — giảm attack surface đáng kể. BanhCuonFlow production: Nginx → API (.NET Kestrel) + frontend (static files pre-built).

⑩ Backup Strategy

Automated daily backup: pg_dump → compress gzip → upload đến S3/external storage (off-site, khác server với database). Test restore monthly — backup không test restore = không có backup (bạn chỉ có file dump mà không biết có restore được không). BanhCuonFlow: PostgreSQL WAL archiving + daily base backup = point-in-time recovery (restore về bất kỳ thời điểm nào trong 7 ngày). Retention: daily backups giữ 7 ngày, weekly giữ 4 tuần, monthly giữ 12 tháng.

Image Scanning: Bảo Mật Trước Khi Deploy

Mỗi Docker image chứa OS packages, libraries, runtime — bất kỳ thứ nào trong đó đều có thể chứa CVE (Common Vulnerabilities and Exposures). Trivy (open-source, Aqua Security) quét image trong CI/CD pipeline: trivy image myapp:latest → liệt kê tất cả CVE, severity (Critical/High/Medium/Low), và fix version nếu có. Docker Scout (tích hợp Docker Desktop) cung cấp continuous monitoring. Nguyên tắc: image có CVE Critical hoặc High → pipeline fail, không cho deploy. Rebuild image weekly với base image mới nhất để apply security patches tự động.

Deploy BanhCuonFlow

Docker Compose production-ready, Nginx reverse proxy, automated backups, health checks. Hướng dẫn triển khai chi tiết từ zero đến production.