🎯 什麼情境該想到我

當你「要一個能測的環境得先開單、等 Ops 好幾週,等到了還跟生產環境對不起來」的時候。

⚙️ 怎麼用(步驟 / 公式)

意圖:讓開發者能在自己的工作站上,隨選、自助地跑起類生產環境,在日常工作中就持續驗證程式碼品質。

做法要點:

  • 不要只把生產環境的規格寫在文件或 wiki 上,而是建立一套共用的建置機制(common build mechanism),用它產生所有環境——development、test、production 都由同一套產生。
  • 判準:任何人都能在幾分鐘內拿到類生產環境,不必開單(without opening up a ticket),更不必等好幾週。
  • 把「已知良好、穩定、安全、風險已降低」的環境定義下來並自動化;所有需求不是放在文件或某個人腦袋裡,而是編碼在自動化環境建置流程中。
  • 六種可用的自動化手段(任選其一或全部):
    1. 複製虛擬化環境(VMware image、跑 Vagrant script、在 EC2 開 Amazon Machine Image)
    2. 從「bare metal」開始的自動化環境建立流程(例如從 baseline image 做 PXE install)
    3. 使用「infrastructure as code」組態管理工具(Puppet、Chef、Ansible、Salt、CFEngine 等)
    4. 使用自動化作業系統組態工具(Solaris Jumpstart、Red Hat Kickstart、Debian preseed)
    5. 由一組虛擬映像檔或容器組裝出環境(Vagrant、Docker)
    6. 在公有雲(AWS、Google App Engine、Microsoft Azure)、私有雲或其他 PaaS(OpenStack、Cloud Foundry)上開新環境
  • 給開發者一個他完全掌控的環境,讓他能安全隔離於生產服務與共用資源之外,快速重現、診斷、修掉缺陷,還能拿環境與建立環境的基礎設施程式碼做實驗。
  • 書中對「環境」的定義:應用程式以外的整個應用堆疊——資料庫、作業系統、網路、虛擬化,以及所有相關組態。所以「類生產環境」要對齊的不只是程式,而是這一整層。

最小可跑範例(自寫範例,對應上面第 5 種手段「由容器組裝出環境」)

專案根目錄放一個 docker-compose.yml(假設專案已有能建出應用的 Dockerfile,應用聽 8080 埠):

services:
  db:
    image: postgres:16          # 版本釘死成跟生產一樣,不要用 latest
    environment:
      POSTGRES_PASSWORD: example   # 示範用的假密碼;正式環境改用 secret 管理
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      retries: 15
  app:
    build: .
    environment:
      DATABASE_URL: postgres://postgres:example@db:5432/postgres
    depends_on:
      db:
        condition: service_healthy   # 等 DB 真的能連才啟動 app
    ports: ["8080:8080"]

一行指令起整套環境、一行拆掉:

docker compose up -d --build     # 幾分鐘內拿到 app + 資料庫,不用開單
docker compose down -v           # 用完連資料卷一起刪,下次從乾淨狀態重建

這就是書中判準的縮小版:環境需求(DB 版本、連線字串、啟動順序)寫在版控裡的檔案中,而不是 wiki 或某人腦袋裡;任何人 clone 下來跑同一行指令都得到同一套環境。要再往「共用建置機制」走一步,就是讓 CI 與測試環境也用同一份定義(或同一批映像檔)建起來,而不是各自維護一份。

原文:「By doing this, anyone can get production-like environments in minutes, without opening up a ticket, let alone having to wait weeks.」(L4653–4654)

原文:「All our requirements are embedded, not in documents or as knowledge in someone’s head, but codified in our automated environment build process.」(L4658–4660)

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 環境建得出來還不夠:若不強制「開發者實際在類生產環境跑自己的碼」,這套機制會閒置,所以書中把它寫進修改完成的定義。
  • 環境本身也是會腐化的資產,必須跟著版本控管一切、不可變基礎設施一起做,否則生產環境仍會靠手動變更漂移。
  • 建置機制若不是「單一共用」的,dev/test/prod 各做各的,就退回「測試環境配置錯誤或與生產差太多」的老問題。
  • 「類生產」永遠不等於「生產」,所以還是會漏 bug(推測):以下幾樣幾乎不可能在隨選環境完整複製——
    • 資料:生產資料的量與「髒」程度(歷史遺留格式、極端值、編碼怪字);拿空表或幾筆假資料測,慢查詢與資料相依的 bug 都看不到。生產資料又多半含個資,不能直接複製下來。
    • 規模與負載:單機 compose 跑不出併發競態、連線池耗盡、跨節點時鐘差。
    • 第三方相依:金流、簡訊、外部 API 只能接 sandbox 或 mock,它們的行為(限流、逾時、錯誤格式)跟正式服務常有落差。
    • 密鑰與權限:生產的 secrets、IAM 權限、網路防火牆規則刻意不給開發環境,導致「權限不足」「連不到」這類問題只會在生產出現。
      所以隨選環境要搭配部署後的生產遙測與安全的發布手法(金絲雀發布、藍綠部署)一起用,不能當成「測過就保證沒事」。
  • 雲端隨選環境沒人拆,費用會一直累積(推測,數字為自寫範例):例如每開一個 PR 就自動建一套雲端預覽環境,每套每小時 0.10 美元,一個月 ≈ 0.10 × 24 × 30 = 72 美元;若有 20 套 PR 早就合併或放棄卻沒拆,每月就白燒約 1,440 美元。對策:環境建立時就綁定拆除條件——PR 關閉自動 destroy、設存活時間(TTL)到期自動刪、資源打上擁有者標籤定期掃描孤兒環境。

🔗 相關工具