iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Software Development

30 天 Python 專案工坊:環境、結構、測試到部署全打通系列 第 12

Day 12 -設定與祕密管理:dotenv、pydantic-settings、雲端祕密服務

  • 分享至 

  • xImage
  •  

在前 11 天,我們已經把專案的「基礎建設」建起來了:環境、設定檔、專案結構、依賴管理、一鍵化工作流、程式風格、型別與資料契約,再到測試藍圖。

專案已經能穩定執行,並且確保品質。

但還缺一塊關鍵拼圖:設定與祕密管理(Configuration & Secrets Management)

這是許多專案會踩的坑:

  • 在程式碼裡硬編 API Key。
  • 在 repo 裡 commit .env
  • 測試環境跟正式環境設定不一致。

今天,我們要建立一個「設定與祕密」的管理藍圖,從最簡單的 .env,到 pydantic-settings,再到雲端祕密服務,逐步提升安全性與工程化程度。


一、.env:最常見的入門解法

許多人一開始會用 .env 搭配 python-dotenv

# .env
APP_ENV=dev
APP_DEBUG=true
DATABASE_URL=postgresql://user:pass@localhost/db

在程式裡讀取:

from dotenv import load_dotenv
import os

load_dotenv()

print(os.getenv("APP_ENV"))       # dev
print(os.getenv("DATABASE_URL"))  # postgresql://user:pass@localhost/db

👉 優點:簡單、直觀、快速上手。

👉 缺點:缺乏型別與驗證,.env 常被誤 commit,祕密容易外洩。

適合用在個人實驗或小型專案,但在團隊專案就需要更嚴謹的工具。


二、pydantic-settings:工程化的設定管理

延續 Day 10 的 Pydantic v2,我們可以用 pydantic-settings 把環境變數「轉換成型別安全的設定物件」。

from pydantic_settings import BaseSettings, SettingsConfigDict

class AppSettings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="APP_")

    env: str = "dev"
    debug: bool = False
    database_url: str

settings = AppSettings()
print(settings.env, settings.debug, settings.database_url)

如果 .env 或環境變數有問題,會直接丟出 ValidationError,這比 os.getenv() 安全得多。

更進一步,我們還可以區分環境設定檔

# .env.dev
APP_ENV=dev
APP_DEBUG=true
APP_DATABASE_URL=sqlite:///local.db

# .env.prod
APP_ENV=prod
APP_DEBUG=false
APP_DATABASE_URL=postgresql://user:pass@prod/db

在程式裡依 CI/CD 或環境參數載入對應設定,避免「開發正常、上線爆炸」。

👉 工程實務的好處:

  • 型別安全(不會把 APP_PORT=abc 認成 int)。
  • 明確邊界(哪些是必填設定,哪些有預設值)。
  • 測試容易(可以在 pytest fixture 中塞入環境變數,檢查設定行為)。

三、雲端祕密服務:進階安全防線

當專案進入團隊或上雲環境,就不該再把祕密留在 .env 了。

常見做法是使用 雲端祕密管理服務

  • AWS Secrets Manager
  • GCP Secret Manager
  • Azure Key Vault

以 AWS 為例,我們可以在部署環境透過 SDK 讀取:

import boto3
import json

client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="my-app/db")
db_config = json.loads(resp["SecretString"])

再把 db_config 餵給 pydantic-settings 的模型,保持型別安全。

👉 好處:

  • 集中管理:祕密不再散落 .env
  • 權限管控:誰能讀取哪個 secret,都在 IAM 控制。
  • 自動輪換:部分雲服務能自動更新金鑰,降低風險。

👉 缺點:

  • 成本增加(需要雲服務支援)。
  • 開發環境需要模擬/快取機制。

最佳實務:本地用 .env 模擬,雲端用 Secret Manager 正式管理


四、專案目錄結構:設定與祕密的歸位

延續 Day 4 的「src/ + tests/」設計,我們可以這樣放置設定與祕密相關檔案:

my_project/
├─ src/my_project/
│   ├─ __init__.py
│   ├─ settings.py        # pydantic-settings 模型
│   ├─ secrets.py         # 雲端 Secrets Manager 讀取工具
│   └─ adapters/
│       └─ web.py
├─ .env.example           # 範例環境變數(不含祕密值)
├─ .gitignore             # 記得忽略 .env、.env.*
└─ tests/
    └─ test_settings.py   # 測試設定與驗證

這樣可以清楚地分層:

  • settings.py:設定模型與驗證。
  • secrets.py:與雲端祕密服務的串接邏輯。
  • .env.example:作為文件,提醒新進開發者需要哪些環境變數。

五、工程化藍圖:本地 → CI → 雲端

把這三層組合起來,我們得到一個設定管理藍圖:

  • 本地開發.env + pydantic-settings,快速迭代。
  • CI 測試:GitHub Actions / GitLab CI 的「Environment Secrets」,避免硬編。
  • 正式環境:AWS/GCP/Azure 的 Secret Manager,搭配 pydantic-settings 載入。

範例 CI 工作流(GitHub Actions):

name: ci
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      APP_ENV: test
      APP_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest -q

這樣就能確保:

  • 開發者不用知道正式密碼。
  • CI/CD 自動注入需要的設定。
  • 雲端環境安全地管理敏感資訊。

六、最佳實務清單(Checklist)

  • .env 永遠不要 commit,僅提供 .env.example
  • 設定用 pydantic-settings 驗證,避免錯誤流入 runtime。
  • 祕密用雲端服務管理,並設定最小權限(Least Privilege)。
  • 在 CI/CD 裡用平台的 Secret 機制,不要偷懶塞 .env
  • 在 PR 流程中加入秘密掃描(如 detect-secrets 或 Gitleaks)。

結語

設定與祕密管理,是工程化專案的安全防線。

  • .env:入門與本地測試。
  • pydantic-settings:型別安全、驗證與分環境管理。
  • 雲端祕密服務:團隊與生產級專案的必備解法。

透過這三層逐步演進,我們可以避免「API Key 洩漏」「環境錯亂」的風險,讓專案在安全性與維護性上更上一層樓 🚀。

明天 Day 13,我們將探討 結構化日誌:logging / structlog 與 JSON Log,看看如何讓專案的日誌不只是文字,而是能被監控與分析的資料流。


上一篇
Day 11 - 測試策略藍圖:pytest 目錄結構、fixtures 與 coverage
下一篇
Day 13 - 結構化日誌:logging/structlog 與 JSON Log
系列文
30 天 Python 專案工坊:環境、結構、測試到部署全打通14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言