Cloud Native 12 Factor 完整解析:打造可擴展雲原生應用的 12 項原則【2025】
Cloud Native 12 Factor 完整解析:打造可擴展雲原生應用的 12 項原則【2025】
你寫的程式在自己電腦上跑得好好的,一上線就出問題。設定檔散落各處,環境變數搞不清楚,每次部署都像在拆炸彈。這些問題,12 Factor App 在十多年前就給出了解答。
12 Factor 是一套經過實戰驗證的雲端應用開發原則。不管你用什麼程式語言、什麼框架,這 12 項原則都適用。讀完這篇文章,你會知道每項原則的具體意義,以及如何在你的專案中落實。

什麼是 12 Factor App?
12 Factor 的起源
12 Factor App 由 Heroku 共同創辦人 Adam Wiggins 在 2011 年提出。當時 Heroku 是最早的 PaaS(Platform as a Service)平台之一,他們累積了大量在雲端環境運行 SaaS 應用的經驗。
這些經驗被整理成 12 項原則,幫助開發者避開常見的坑。雖然已經過了十多年,這些原則到今天仍然適用,甚至成為 Cloud Native 應用的基礎標準。
為什麼 12 Factor 重要?
12 Factor 解決的是這些問題:
- 環境不一致:開發環境可以跑,生產環境就掛
- 部署困難:每次上線都要手動改一堆設定
- 擴展受限:應用程式無法水平擴展
- 維護困難:新人接手專案要花很長時間理解
遵循 12 Factor 原則的應用程式:
- 可以在不同環境間無縫移植
- 適合部署在雲端平台
- 可以輕鬆水平擴展
- 減少開發和維運之間的差異
12 Factor 與 Cloud Native 的關係
12 Factor 比 Cloud Native 這個詞出現得更早,但它的理念完全符合 Cloud Native 架構的要求。事實上,如果你想導入 Kubernetes 或微服務架構,遵循 12 Factor 是最基本的前提。
CNCF 後來提出的許多最佳實踐,都可以追溯到 12 Factor 的原則。可以說,12 Factor 是 Cloud Native 的地基。
想了解 Cloud Native 完整概念?請參考 Cloud Native 完整指南:雲原生是什麼?。
12 項原則完整解析
1. Codebase(程式碼基底)
一份程式碼基底,多個部署環境
原則說明:
一個應用程式應該只有一份程式碼,存放在版本控制系統(如 Git)中。這份程式碼可以部署到多個環境(開發、測試、生產),但程式碼本身只有一份。
正確做法:
my-app/
├── src/
├── package.json
└── .git/
# 透過 CI/CD 部署到不同環境
dev.example.com ← 同一份程式碼
staging.example.com ← 同一份程式碼
prod.example.com ← 同一份程式碼
違反的情況:
- 開發環境和生產環境用不同的程式碼版本
- 針對不同客戶 fork 出不同版本的程式碼
- 把共用程式碼複製貼上到多個專案
為何重要:
程式碼分散會導致版本混亂。一個 bug 修了這邊,忘了修那邊。遵循這個原則,任何變更都能追蹤,任何環境的問題都能重現。
2. Dependencies(依賴管理)
明確宣告並隔離依賴
原則說明:
應用程式不應該依賴系統層級的套件。所有依賴都應該在依賴清單(如 package.json、requirements.txt、pom.xml)中明確宣告。
正確做法:
// package.json
{
"dependencies": {
"express": "^4.18.0",
"pg": "^8.11.0",
"redis": "^4.6.0"
}
}
違反的情況:
- 程式碼假設系統已經安裝了某個命令列工具
- 使用未宣告的全域套件
- README 寫著「請先手動安裝 ImageMagick」
為何重要:
明確宣告依賴,新人可以用一個指令就把開發環境架好。部署時也不會因為「這台機器少裝了什麼」而出錯。
3. Config(配置外部化)
設定存在環境變數中
原則說明:
設定(資料庫連線、API 金鑰、服務端點)不應該寫在程式碼裡。應該透過環境變數注入,讓同一份程式碼可以在不同環境使用不同設定。
正確做法:
// 從環境變數讀取設定
const dbHost = process.env.DATABASE_HOST;
const apiKey = process.env.API_KEY;
違反的情況:
// 寫死在程式碼裡(錯誤)
const dbHost = 'prod-db.example.com';
const apiKey = 'sk-1234567890';
為何重要:
- 避免把機密資訊提交到 Git
- 不同環境使用不同設定,不需要改程式碼
- 安全性:機密資訊不會外洩到程式碼倉庫
判斷標準:
問自己:這份程式碼可以立即開源嗎?如果開源會洩漏機密,那就是設定寫錯地方了。
4. Backing Services(後端服務)
把後端服務當作附加資源
原則說明:
資料庫、快取、訊息佇列、Email 服務等,都應該當作可抽換的「附加資源」。應用程式不應該區分「本地服務」和「第三方服務」。
正確做法:
# 透過環境變數指定服務位置
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
REDIS_URL=redis://localhost:6379
SMTP_URL=smtp://sendgrid.net:587
切換資料庫?只要改環境變數,不需要改程式碼。
違反的情況:
- 程式碼假設資料庫一定在 localhost
- 硬編碼服務的 IP 位址
- 本地開發用 SQLite,生產用 PostgreSQL(但程式碼有差異)
為何重要:
雲端環境的服務經常變動。資料庫可能遷移、快取服務可能換供應商。遵循這個原則,這些變動不需要改程式碼,只要改設定。
Kubernetes 如何實踐這項原則?請參考 Cloud Native 技術棧入門,了解 K8s 的 Service 和 ConfigMap 機制。
5. Build, Release, Run(建置、發布、執行)
嚴格分離建置和執行階段
原則說明:
程式碼到執行之間,應該經過三個階段:
- Build(建置):把程式碼編譯成可執行的 artifact
- Release(發布):把 build 產物和設定結合,產生可部署的版本
- Run(執行):在執行環境中啟動應用程式
正確做法:
程式碼 → [Build] → Docker Image
Docker Image + Config → [Release] → v1.2.3
v1.2.3 → [Run] → 執行中的容器
每個 Release 都應該有唯一的版本號,方便追蹤和回滾。
違反的情況:
- 直接在生產環境修改程式碼
- Build 時寫入設定值
- 沒有版本號,不知道現在跑的是哪個版本
為何重要:
嚴格分離這三個階段,可以確保:
- 同一個 build 可以部署到不同環境
- 出問題時可以快速回滾到上一個版本
- 每個版本都可重現
6. Processes(無狀態流程)
把應用程式當作無狀態的流程執行
原則說明:
應用程式的每個實例(process)都應該是無狀態的。任何需要持久化的資料都應該存在外部服務(資料庫、快取)。
正確做法:
// 使用 Redis 存 session
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET
}));
違反的情況:
// 把資料存在記憶體裡(錯誤)
const userSessions = {};
app.post('/login', (req, res) => {
userSessions[req.body.userId] = { loggedIn: true };
});
為何重要:
無狀態的應用程式才能水平擴展。如果狀態存在記憶體裡,增加一台伺服器就會造成資料不一致。
這也是為什麼 Kubernetes 可以隨時重啟 Pod 而不影響服務——因為 Pod 本身不存重要資料。
7. Port Binding(端口綁定)
透過 Port 綁定對外提供服務
原則說明:
應用程式應該自己綁定一個 Port 來對外提供服務,而不是依賴外部的 Web Server(如 Apache、Nginx)來處理請求。
正確做法:
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
違反的情況:
- 程式碼假設前面一定有 Apache 或 Nginx
- 沒有定義如何對外暴露服務
為何重要:
容器環境中,每個容器都是獨立的單位。它應該自己知道如何對外提供服務,而不是依賴外部設定。這讓應用程式可以被當作其他應用的「backing service」使用。
8. Concurrency(併發)
透過 Process 模型水平擴展
原則說明:
應用程式應該透過增加 process 數量來處理更多負載,而不是把單一 process 變得更大(加更多 CPU、RAM)。
擴展模型:
┌─────────────────────────────────────┐
│ Web (3 instances) │
│ ├─ web.1 ├─ web.2 ├─ web.3 │
├─────────────────────────────────────┤
│ Worker (2 instances) │
│ ├─ worker.1 ├─ worker.2 │
├─────────────────────────────────────┤
│ Clock (1 instance) │
│ └─ clock.1 │
└─────────────────────────────────────┘
違反的情況:
- 用單一程序處理所有事情
- 用多線程(thread)來擴展,但無法跨機器
- 假設只會有一個實例在執行
為何重要:
水平擴展比垂直擴展更靈活、更經濟。Kubernetes 的 HPA(Horizontal Pod Autoscaler)就是基於這個概念——流量大時自動增加 Pod 數量。

9. Disposability(可處置性)
快速啟動、優雅關閉
原則說明:
應用程式應該可以在幾秒內啟動,也可以優雅地關閉。這讓系統可以快速擴展、快速部署、快速恢復。
正確做法:
// 處理關閉信號
process.on('SIGTERM', async () => {
console.log('Received SIGTERM, shutting down gracefully');
// 停止接受新請求
server.close();
// 完成進行中的請求
await finishPendingRequests();
// 關閉資料庫連線
await db.close();
process.exit(0);
});
違反的情況:
- 啟動需要好幾分鐘
- 關閉時直接殺掉 process,不處理進行中的請求
- 沒有處理 SIGTERM 信號
為何重要:
Kubernetes 在重新部署或縮減 Pod 時,會發送 SIGTERM 給容器。如果容器沒有優雅關閉,進行中的請求會失敗,使用者會看到錯誤。
12 Factor 聽起來簡單,落地卻不容易。預約架構諮詢,讓有經驗的人幫你避開實作的坑。
10. Dev/Prod Parity(開發/生產一致性)
保持開發、測試、生產環境一致
原則說明:
開發環境和生產環境之間的差異應該越小越好。這包括:
- 時間差距:開發完到部署的時間越短越好
- 人員差距:開發者也應該參與部署
- 工具差距:開發和生產使用相同的技術棧
正確做法:
# docker-compose.yml 用於本地開發
services:
db:
image: postgres:15 # 和生產環境一樣
redis:
image: redis:7 # 和生產環境一樣
app:
build: .
environment:
- DATABASE_URL=postgres://...
違反的情況:
- 開發用 SQLite,生產用 PostgreSQL
- 開發用 Windows,生產用 Linux
- 開發環境落後生產環境好幾個版本
為何重要:
環境差異是「在我電腦上可以跑」問題的根源。Docker 和容器技術的出現,讓維持環境一致變得容易許多。
11. Logs(日誌即事件流)
把日誌當作事件流處理
原則說明:
應用程式不應該管理自己的日誌檔案。它應該把日誌寫到標準輸出(stdout),讓執行環境來決定如何收集和儲存。
正確做法:
// 寫到 stdout
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'info',
message: 'User logged in',
userId: user.id
}));
違反的情況:
// 寫到檔案(錯誤)
const fs = require('fs');
fs.appendFileSync('/var/log/app.log', 'User logged in\n');
為何重要:
在容器環境中,容器是暫時的。把日誌寫到容器內的檔案,容器一刪除日誌就不見了。
寫到 stdout 的日誌可以被 Kubernetes 收集,送到 Elasticsearch、CloudWatch 等集中式日誌系統。這讓你可以跨所有實例搜尋和分析日誌。
12. Admin Processes(管理流程)
把管理任務當作一次性程序執行
原則說明:
資料庫遷移、資料清理、維護腳本等管理任務,應該在和應用程式相同的環境中執行,使用相同的程式碼和設定。
正確做法:
# 在 K8s 中用 Job 執行資料庫遷移
kubectl run db-migrate \
--image=myapp:v1.2.3 \
--env="DATABASE_URL=$DATABASE_URL" \
--command -- npm run migrate
違反的情況:
- 直接 SSH 到生產伺服器執行腳本
- 用不同版本的程式碼執行管理任務
- 管理腳本沒有進版本控制
為何重要:
管理任務和應用程式面對同樣的環境變數、同樣的資料庫、同樣的設定。在不同環境執行,可能會因為版本不一致造成問題。

15 Factor 擴充版
隨著 Cloud Native 發展,社群發現原始的 12 Factor 需要補充一些現代實踐。以下是常被提及的 3 項額外原則:
13. API First
原則說明:
設計時優先考慮 API 介面。在寫實作程式碼之前,先定義 API 契約(OpenAPI、GraphQL Schema)。
為什麼需要這項原則:
- 微服務架構中,服務間透過 API 溝通
- 前後端分離的開發模式需要清楚的 API 規格
- API 契約可以用來自動產生文件和 SDK
14. Telemetry
原則說明:
應用程式應該內建可觀測性(Observability)能力:
- Metrics:效能指標(請求數、延遲、錯誤率)
- Tracing:分散式追蹤(一個請求經過哪些服務)
- Logging:結構化日誌
為什麼需要這項原則:
在微服務架構中,傳統的除錯方式不再適用。你需要能夠跨服務追蹤一個請求的完整路徑。
OpenTelemetry 是目前 CNCF 推動的標準,可以同時處理 metrics、tracing 和 logging。
15. Security
原則說明:
安全性應該內建在應用程式中,而不是事後加上的防護層。這包括:
- 依賴項的安全掃描
- 機密管理(不把密碼存在環境變數的明文)
- 最小權限原則
- 容器映像的安全掃描
為什麼需要這項原則:
傳統的邊界安全(防火牆、WAF)在 Cloud Native 環境中不夠用。零信任架構要求每個服務都要驗證和授權。
想深入了解 Cloud Native 安全?請參考 Cloud Native Security 完整指南。
12 Factor 實踐範例
以下用一個 Node.js 應用程式示範如何遵循 12 Factor:
專案結構:
my-app/
├── src/
│ ├── index.js
│ ├── config.js
│ └── routes/
├── package.json
├── Dockerfile
├── docker-compose.yml
└── .env.example
config.js(第 3 原則:Config):
module.exports = {
port: process.env.PORT || 3000,
database: {
url: process.env.DATABASE_URL,
},
redis: {
url: process.env.REDIS_URL,
},
logLevel: process.env.LOG_LEVEL || 'info',
};
Dockerfile(第 2、5 原則:Dependencies、Build):
FROM node:20-alpine
WORKDIR /app
# 明確宣告依賴
COPY package*.json ./
RUN npm ci --only=production
COPY src/ ./src/
# 透過環境變數注入設定
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "src/index.js"]
index.js(第 7、9、11 原則:Port Binding、Disposability、Logs):
const express = require('express');
const config = require('./config');
const app = express();
// 第 7 原則:Port Binding
const server = app.listen(config.port, () => {
// 第 11 原則:Logs 到 stdout
console.log(JSON.stringify({
level: 'info',
message: `Server started on port ${config.port}`,
timestamp: new Date().toISOString()
}));
});
// 第 9 原則:Disposability - 優雅關閉
process.on('SIGTERM', () => {
console.log(JSON.stringify({
level: 'info',
message: 'SIGTERM received, shutting down gracefully'
}));
server.close(() => {
console.log(JSON.stringify({
level: 'info',
message: 'Server closed'
}));
process.exit(0);
});
});
Spring Boot 如何實踐 12 Factor?請參考 Cloud Native Java 開發指南。
12 Factor 快速參考表
| # | 原則 | 一句話 | 檢查項目 |
|---|---|---|---|
| 1 | Codebase | 一份程式碼,多個部署 | 程式碼在 Git?只有一份? |
| 2 | Dependencies | 明確宣告依賴 | package.json 完整? |
| 3 | Config | 設定在環境變數 | 沒有 hardcode 的密碼? |
| 4 | Backing Services | 服務可抽換 | 換資料庫要改程式碼嗎? |
| 5 | Build, Release, Run | 階段分離 | 有 CI/CD?有版本號? |
| 6 | Processes | 無狀態 | Session 存外部? |
| 7 | Port Binding | 自己綁 Port | 不依賴 Apache/Nginx? |
| 8 | Concurrency | 水平擴展 | 可以跑多個實例? |
| 9 | Disposability | 快啟動、優雅關閉 | 處理 SIGTERM? |
| 10 | Dev/Prod Parity | 環境一致 | 開發用 Docker? |
| 11 | Logs | 寫 stdout | 沒有寫檔案? |
| 12 | Admin Processes | 一次性任務 | 遷移腳本在版控? |
FAQ
Q1: 12 Factor 是強制規定還是建議?
12 Factor 是建議性的最佳實踐,不是強制規定。但如果你想在 Kubernetes 等 Cloud Native 環境順利運行應用程式,遵循這些原則會讓事情簡單很多。
Q2: 一定要全部遵循才算合格嗎?
不一定。根據你的應用程式需求,某些原則可能不適用。但核心的幾項(Config、Stateless Processes、Logs)幾乎是 Cloud Native 的必要條件。
Q3: 12 Factor 和微服務有什麼關係?
12 Factor 最初是為單體式 SaaS 應用設計的,但它的原則同樣適用於微服務。事實上,微服務架構更需要遵循這些原則,因為服務數量更多、環境更複雜。
Q4: 我的遺留系統能套用 12 Factor 嗎?
可以逐步導入。通常從設定外部化(第 3 原則)和日誌標準化(第 11 原則)開始最容易,然後再處理無狀態和依賴管理。
Q5: 15 Factor 是官方標準嗎?
不是。15 Factor 是社群根據 Cloud Native 發展補充的建議,沒有官方認證。但 API First、Telemetry、Security 這三項確實是現代雲端應用的重要考量。
下一步
12 Factor 是 Cloud Native 架構的基礎。掌握這些原則後,你可以進一步探索:
- 回到核心概念:Cloud Native 完整指南
- 了解 Kubernetes 實踐:Cloud Native 技術棧入門
- 學習 Java 雲原生開發:Cloud Native Java 開發指南
- 強化安全性:Cloud Native Security 完整指南
架構設計需要第二意見?12 Factor 看起來簡單,但要在既有系統中落實並不容易。預約架構諮詢,讓有經驗的專家幫你評估現況,規劃改善路徑。
參考資料
相關文章
Cloud Native 完整指南:雲原生是什麼?架構、原則與實戰入門【2025】
Cloud Native 是什麼?完整解析雲原生定義、12 Factor 原則、CNCF 生態系、K8s 容器化架構。從入門到實戰,一篇搞懂 Cloud Native 雲原生架構!
Cloud Native5G Cloud Native Architecture:電信商如何實現雲原生 5G 核心網路【2025】
5G 與 Cloud Native 如何結合?本文解析 5G Cloud Native Architecture、5G Core Network 雲原生架構、3GPP 標準與 Cloud Native 的關係,以及電信商導入案例。
Cloud NativeCloud Native AI:如何在雲原生環境中建構 AI/ML 工作流程【2025】
如何在 Cloud Native 環境建構 AI/ML 工作流程?本文介紹 MLOps 與雲原生整合、Kubeflow 平台、GPU 資源管理,以及 AI 模型在 Kubernetes 上的部署與擴展策略。