Backend

99 Ngày Spring — Ngày 91: Config và Secrets cho Production

SSite Admin
26 tháng 10, 2026 3 phút đọc 5 lượt xem
99 Ngày Spring — Ngày 91: Config và Secrets cho Production

Cùng một bản build phải chạy được ở dev, staging và production; thứ khác nhau giữa các môi trường là cấu hình. Nguyên tắc 12-factor nói cấu hình nằm ở môi trường, không nằm trong code. Spring Boot hỗ trợ sẵn điều đó, nhưng secret cần thêm một lớp kỷ luật: không vào Git, không vào image, không vào log.

Config và Secrets cho Production

1. Cấu hình đến từ môi trường

Spring Boot đọc property từ nhiều nguồn và nguồn bên ngoài thắng nguồn đóng gói: tham số dòng lệnh, rồi biến môi trường, rồi file cấu hình bên ngoài jar, rồi mới tới application.yml trong jar. Relaxed binding ánh xạ biến SPRING_DATASOURCE_URL thành spring.datasource.url. Vì vậy application.yml trong jar chỉ nên chứa giá trị mặc định an toàn, còn giá trị riêng của từng môi trường được truyền vào lúc chạy.

# packaged defaults (application.yml)
payment:
  base-url: http://localhost:9090
  timeout: 2s

# production, supplied by the platform
# PAYMENT_BASE_URL=https://pay.internal.example
# PAYMENT_TIMEOUT=1s
# SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shop

2. @ConfigurationProperties có kiểm tra

Gom cấu hình của một tính năng vào một record có kiểu thay vì rải @Value khắp nơi. Thêm @Validated và các ràng buộc Bean Validation để ứng dụng từ chối khởi động khi thiếu hoặc sai cấu hình. Lỗi lúc khởi động rẻ hơn nhiều so với NullPointerException ở request đầu tiên vào lúc nửa đêm.

@Validated
@ConfigurationProperties("payment")
record PaymentProperties(
        @NotNull URI baseUrl,
        @NotNull @DurationMin(millis = 100) Duration timeout,
        @NotBlank String apiKey) {}

@SpringBootApplication
@ConfigurationPropertiesScan
class ShopApplication {}

3. Secret: không Git, không image, không log

Secret là cấu hình mà lộ ra thì gây thiệt hại: mật khẩu database, API key, khóa ký JWT. Nền tảng chạy ứng dụng nên cấp chúng lúc chạy, qua biến môi trường hoặc tốt hơn là file được mount. Spring Boot đọc được cả thư mục secret bằng configtree: mỗi file là một property, tên file là key, nội dung là giá trị. Với hệ thống lớn, dùng secret manager như Vault hoặc dịch vụ của cloud để có phân quyền, nhật ký truy cập và xoay vòng.

# /run/secrets/payment.api-key  -> property payment.api-key
spring.config.import=optional:configtree:/run/secrets/

4. Kỷ luật vận hành

Actuator endpoint /env và /configprops che giá trị theo mặc định từ Spring Boot 3; đừng mở lại ở production. Profile dùng để bật nhóm bean khác nhau, không dùng để cất mật khẩu trong application-prod.yml. Khi một secret đã lỡ vào Git, xóa commit là chưa đủ: phải coi như đã lộ và xoay vòng ngay.

  • Một image cho mọi môi trường; chỉ cấu hình thay đổi.

  • Mỗi môi trường và mỗi service có secret riêng, quyền tối thiểu.

  • Không in toàn bộ cấu hình hay header Authorization ra log.

  • Bật quét secret trong CI để chặn trước khi merge.

  • Có quy trình xoay vòng đã được diễn tập, không đợi đến khi có sự cố.

Cấu hình tốt là cấu hình sai thì ứng dụng không khởi động, và secret tốt là secret xoay vòng được. Ngày 92 làm cho log của production trở nên tra cứu được.

Tài liệu đối chiếu

  • https://docs.spring.io/spring-boot/reference/features/external-config.html

  • https://12factor.net/config

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Java — Ngày 91: SOLID

Năm nguyên tắc thiết kế hướng đối tượng kèm ví dụ Java, và cách nhận ra code smell báo hiệu chúng bị vi phạm.

26 thg 10, 20263 phút6
99 Ngày Spring — Ngày 90: Docker Compose cho Dev

compose.yaml cho Postgres, Redis và Kafka, spring-boot-docker-compose tự khởi động và tự nối kết, cùng ranh giới với Testcontainers.

25 thg 10, 20262 phút4
99 Ngày Java — Ngày 90: Tổ chức Project và Clean Code

Package theo feature, đặt tên nói lên ý định, hàm nhỏ với guard clause và những nguyên tắc clean code dùng được ngay.

25 thg 10, 20263 phút4