Bỏ qua để đến nội dung
Knowledge Hub

12-factor và build once, deploy many: config nằm ở môi trường Trung cấp

Thời gian đọc ước tính: 3 phút

Trang này trả lời: 12-factor thực sự nói gì về config, và vì sao cùng một image phải đi từ staging lên production.

12-factor có 12 nguyên tắc; ba cái liên quan trực tiếp:

Factor Nguyên văn Hệ quả thực tế
III. Config “Store config in the environment” Config đọc từ env var, không nằm trong code hay image
V. Build, release, run “Strictly separate build and run stages” Build ra một artifact; release = build kết hợp config của deploy đó
X. Dev/prod parity “Keep development, staging, and production as similar as possible” Cùng loại backing service, cùng cách nạp config ở mọi môi trường

Định nghĩa gốc: config là “everything that is likely to vary between deploys”.

Phép thử của 12-factor: codebase có thể open source bất cứ lúc nào mà không lộ credential không?

  • 12-factor không coi config nội bộ (route, wiring DI) là config. Thứ không đổi theo deploy thì để trong code.
  • 12-factor khuyên env var là “granular controls”, không gom thành nhóm “environments” như config.production.json.

Code kiểu if (NODE_ENV === 'production') timeout = 5000 chính là gom nhóm trá hình. Ví dụ bad/good ở Lỗi hay gặp.

App ghi log ra stdout (“writes its event stream, unbuffered, to stdout”) và để môi trường định tuyến.

Hệ quả: đường dẫn file log không phải là config app cần biết. Không cần LOG_FILE_PATH.

Cùng một image cho staging và production; thiếu config thì Pod mới không bao giờ ready
Cùng một image cho staging và production; thiếu config thì Pod mới không bao giờ readyBước 1/5: CI build đúng một lần cho mỗi commit và đẩy image có tag theo git SHA. Image không chứa URL, password hay tên môi trường.CI buildchạy 1 lần / commitImage sha-3f9c2e1immutable, có digestPod stagingconfig stagingConfigMap + Secretconfig productionPod v2 productioncùng imagePod v1 productionbản đang chạyđang phục vụpush image
CI build → Image sha-3f9c2e1push image
Bước 1/5

CI build đúng một lần cho mỗi commit và đẩy image có tag theo git SHA. Image không chứa URL, password hay tên môi trường.

Hệ quả của factor V: image không biết nó đang chạy ở đâu. Không có npm run build:prod, không bake .env.production vào image.

Lý do Giải thích
Test đúng thứ sẽ chạy Staging test đúng byte sẽ lên production. Build lại cho production là chạy một artifact chưa từng được test.
Rollback rẻ Rollback là chạy lại digest cũ với config hiện tại, không cần build.
Image không chứa bí mật Image có password bên trong thì ai pull được image là đọc được password.

Docker docs nói thẳng: build argument và env var “are inappropriate for passing secrets to your build” vì “they persist in the final image”. Cần secret lúc build (vd token npm private) thì dùng secret mount.

Ngoại lệ thường gặp: frontend build-time variable (bundler thay giá trị vào JS lúc build). Với backend, không có lý do chính đáng để làm vậy.

# staging và production dùng CÙNG digest, chỉ khác ConfigMap/Secret
image: registry.example.com/payment-api@sha256:...
  • Tag (:latest, :1.4.2) có thể bị ghi đè; digest thì không.
  • Pipeline promote = đổi môi trường đích, không chạy lại docker build.

Tiếp theo: Parse và validate env.