LASSIC Media らしくメディア
Twelve-Factor Appの12原則と今の読み替え方
監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)
この記事の結論
- Twelve-Factor Appは、アプリと実行基盤の間の約束を12の原則にまとめた、2011年に生まれた方法論です。
- 設定・ログ・ステートレスなプロセス・停止の扱い・ビルドと実行の分離は、今もそのまま実務で通用します。
- 原文の最終更新は2017年で改訂も途中のため、依存関係や管理プロセスなどは今の道具に置き換えて読みます。
※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。
Twelve-Factor Appは、Webサービスとして動くアプリケーションを、クラウドに載せやすく、開発環境と本番環境の差が小さい形で作るための12の原則です。アプリの実行基盤を提供するHerokuの開発者たちが2011年にまとめ、設定を環境変数に置く、ログを標準出力へ流すといった、今では当たり前になった作法の出どころになりました。
ただし原文の最終更新は2017年で、例に挙がる道具には古いものも混じります。本記事では、システム開発や運用を担当する方に向けて、12の原則を「今も実務でそのまま使える因子」と「コンテナの時代に読み替えが要る因子」に分けて整理し、Pythonの短い例、つまずきやすい点、外部に委託するときに確かめたい点までをまとめます。
目次
Twelve-Factor Appとは
公式サイトは、Twelve-Factor Appを、ソフトウェアをサービスとして提供するアプリケーションを作るための方法論と位置づけています。*1 目的には、実行環境の間で持ち運びやすくすること、開発と本番の差を小さくして継続的なデプロイを可能にすることなどを挙げ、言語やデータベースの種類は問いません。
12の原則は、アプリと、それを動かす基盤(プラットフォーム)との間の約束事として読むと分かりやすくなります。アプリは設定を環境変数から受け取り、ログを標準出力に書き、いつ止められても困らないように作る。基盤は設定の受け渡し、ログの収集、プロセスの起動と停止を引き受ける。この線引きがあるので、同じコードを手元でもクラウドでも動かせます。
| 因子 | 原文の要旨 | 本記事での扱い |
|---|---|---|
| I. コードベース | 1つのアプリに1つのコードベース。そこから複数の環境へデプロイする | 読み替え |
| II. 依存関係 | 依存するものをすべて宣言し、実行時に分離する | 読み替え |
| III. 設定 | デプロイごとに変わる値を環境変数に置く | そのまま |
| IV. バックエンドサービス | データベースなどを付け替えのきく資源として扱う | 読み替え |
| V. ビルド、リリース、実行 | 3つの段階を厳密に分ける | そのまま |
| VI. プロセス | ステートレスで何も共有しないプロセスとして動かす | そのまま |
| VII. ポートバインディング | アプリがポートで待ち受けてサービスを公開する | 読み替え |
| VIII. 並行性 | プロセスの数を増やしてスケールアウトする | 読み替え |
| IX. 廃棄容易性 | 速く起動し、停止の合図で行儀よく終わる | そのまま |
| X. 開発/本番一致 | 開発・検証・本番の差をできるだけ小さくする | 読み替え |
| XI. ログ | ログをイベントの流れとして標準出力へ書く | そのまま |
| XII. 管理プロセス | 一回限りの管理作業を通常と同じ環境で動かす | 読み替え |
表の「本記事での扱い」は公式の分類ではありません。考え方は今も通用するものの、原文の例や手段が古くなり、置き換えて読む必要がある因子があります。その分け方を図にまとめました。
今もそのまま使える5つの因子
1つ目は設定(III)です。原文は、データベースの接続先、外部サービスの認証情報、ホスト名など、デプロイごとに変わりうるものを設定と定義し、それをコードに定数として書くことを原則への違反としています。*2 確かめ方として示している「認証情報を漏らさずに、今すぐコードを公開できるか」という基準は、コードレビューでもそのまま使えます。環境変数の仕組みそのものは「環境変数の基礎」で扱っています。
2つ目はビルド、リリース、実行の分離(V)です。コードを実行できる形にまとめるビルド、ビルドに設定を組み合わせるリリース、それを動かす実行の3段階を厳密に分け、リリースには一意のIDを付けて、作った後は変更しないという考え方です。コンテナイメージを一度だけ作り、同じイメージに環境ごとの設定を渡して動かす今の進め方は、この因子をそのまま形にしたものといえます。
3つ目のプロセス(VI)と4つ目の廃棄容易性(IX)は、組にして読みます。プロセスはステートレスで何も共有せず、残すべきデータはデータベースなどのバックエンドサービスに置きます。メモリやローカルのディスクは1回の処理の一時置き場としてだけ使い、次のリクエストも同じプロセスに届く前提の「スティッキーセッション」は違反とされています。*3 そのうえで起動は速くし、停止の合図(SIGTERM)を受けたら新しい受付をやめ、処理中のリクエストを終えてから終了します。ワーカーなら処理中のジョブをキューに戻します。*4 台数の増減や更新のたびの入れ替えは、この2つが前提です。
5つ目はログ(XI)です。アプリはログの送り先や保存を気にかけず、ログファイルを自分で書いたり管理したりしない。各プロセスはイベントの流れをバッファせずに標準出力へ書き、集めて保管するのは実行環境の役目、という線引きです。*5 ログの項目をそろえて検索や集計をしやすくする設計は、「構造化ログ基盤の導入を外注で進める」で取り上げています。
具体例:設定を環境変数から読む
設定(III)とログ(XI)を、Pythonの最小例で確かめます。必須の設定が環境変数に無ければ、起動の時点でエラーを出して止めます。起動の時点で止まれば、どの設定が足りないのかがすぐに分かります。
import json
import os
import sys
REQUIRED = ["DATABASE_URL", "SECRET_KEY"]
def load_config():
missing = [k for k in REQUIRED if not os.environ.get(k)]
if missing:
print("missing env: " + ", ".join(missing), file=sys.stderr)
sys.exit(1)
return {
"database_url": os.environ["DATABASE_URL"],
"port": int(os.environ.get("PORT", "8000")),
}
if __name__ == "__main__":
cfg = load_config()
print(json.dumps({"event": "start", "port": cfg["port"]}), flush=True)
Python 3.12.10で実行した結果は次のとおりです。1回目は環境変数を何も渡さずに起動し、2回目は2つの必須項目だけを渡しています。
$ python app.py
missing env: DATABASE_URL, SECRET_KEY
$ echo $?
1
$ DATABASE_URL=postgres://db.internal/app SECRET_KEY=dummy python app.py
{"event": "start", "port": 8000}
1回目は足りない項目名を標準エラーに出し、終了コード1で止まりました。2回目は起動を知らせる1行をJSON形式で標準出力に書き、渡していないPORTには既定の8000が使われました。コードは同じまま、渡す値を変えるだけで開発・検証・本番を切り替えられます。起動ログに接続先や鍵の値を書き出さないことも基本です。
今は読み替えが要る7つの因子
残る7つの因子は、原文の例や手段をそのまま当てはめると今の環境と合わない部分があります。依存関係(II)は、システム全体に入っているパッケージに暗黙に頼らず、依存するものをすべて宣言して分離するよう求め、ImageMagickやcurlのようなOSの道具にも頼らず、必要なら同梱するよう書いています。今はOSの道具まで含めてコンテナイメージに固めるのが一般的で、宣言と分離の単位がライブラリからイメージへ広がったと考えると分かりやすいでしょう。両者の違いは「コンテナと仮想マシンの違い」で整理しています。
開発/本番一致(X)も同じ流れで読めます。原文が挙げる、開発はSQLite、本番はMySQLといった道具の差は、今は手元でも同じ種類のデータベースをコンテナで動かせば縮められます。
ポートバインディング(VII)は、アプリがWebサーバーを内蔵し、ポートで待ち受けてサービスを公開する原則で、コンテナでもそのまま通用します。ただし例に出てくるTornadoやThinは、今では選ばれにくい道具です。並行性(VIII)は、処理の種類ごとにプロセスを分け、数を増やしてスケールアウトする考え方で、プロセスをデーモン化したりPIDファイルを書いたりせず、OSのプロセス管理に任せるよう求めています。今はこの役目をsystemdやコンテナの実行基盤が受け持ちます。
管理プロセス(XII)は、データベースのマイグレーションなど一回限りの作業を、通常のプロセスと同じリリース、つまり同じコードと設定で動かす原則です。原文は本番ではsshなどで実行するとしていますが、今は同じイメージから一回限りのジョブとして起動し、実行の記録を残す形が扱いやすいでしょう。バックエンドサービス(IV)は、データベースなどをURLと認証情報で接続する、付け替えのきく資源として扱う原則で、管理サービスへの移行に今も役立ちます。一方で、改訂の作業では認証やサービス間の通信が、これから取り組む難しい課題に挙げられています。*6 コードベース(I)の「1つのアプリに1つのコードベース」も、複数のアプリを1つのリポジトリで管理する構成をとる場合は、アプリの単位をどこで区切るのかを先に決めておく必要があります。
2024年のオープンソース化と改訂
Herokuは2024年11月12日、Twelve-Factor Appをオープンソースのプロジェクトにすると発表しました。*7 公式ブログは、2011年にHerokuが最初にまとめた文書を、アプリ・フレームワーク・基盤の開発者が集まって今の時代に合わせて改めると説明しています。*8 GitHubのリポジトリは、いずれ12factor.netの文書を置き換える改訂版の置き場とされ、変更は維持管理者たちが一区切りと合意するまで「next」ブランチで進めると書かれています。*9
改訂の方針は、原則と例を切り分け、例を今の実務に合わせて更新するところから始めるとされ、因子の数は12のまま保つと明記されています。*6 2026年10月1日に確かめた時点では、12factor.netの本文は「Last updated 2017」の表示のままでした。nextブランチには2025年3月に複数の因子の改稿が入り、最後の更新は2025年7月で、正式な改訂版はまだ公開されていません。*9
つまずきやすい点
まず、環境変数は秘密情報の金庫ではありません。環境変数の値は子プロセスに引き継がれ、障害時の出力やデバッグ用の画面に表示されることもあるため、例外の出力やログに載らないよう気を配ります。Kubernetesでも、Secretは既定ではAPIサーバーの裏にあるデータストア(etcd)に暗号化されずに保存されると明記されており、*10 保存時の暗号化や参照できる権限の絞り込みは別に設定が要ります。
次に、設定を「development」「staging」「production」のような名前付きの組でまとめる方式です。原文は、デプロイが増えるたびに組の名前が増えて管理が壊れやすくなるとして、環境変数を1つずつ独立に、デプロイごとに管理するよう求めています。*2
三つ目は、コンテナの中でログをファイルに書く構成です。コンテナを入れ替えるとファイルごと消え、集める仕組みからも見えません。四つ目は停止の扱いです。SIGTERMを受けても終わらないアプリは、猶予の時間(Kubernetesの既定では30秒)が過ぎると強制終了され、処理中のリクエストやジョブが途中で切れます。*11 時間のかかる処理は、やり直しても結果が変わらない(冪等な)作りにしておくと、途中で止まっても問題なく再実行できます。
外部に委託するときに確認しておきたい点
既存のアプリをコンテナへ移す作業を委託するときは、12の原則を点検表として使うと話が具体的になります。最初に確かめたいのは設定の棚卸しです。コードや設定ファイルに埋め込まれた接続先や認証情報を誰が洗い出し、どこへ移し、秘密情報をどの仕組みで管理するのかを、提案の段階で示してもらいます。
次に、ステートレス化の範囲です。セッションをメモリに持つ、アップロードされたファイルをローカルのディスクに置く、といった作りが残っていると、台数を増やした途端に不具合が出ます。どれを改修し、どれを残すのか、判断と理由を文書で残してもらいます。あわせて、標準出力に切り替えたログの集め先と保管期間、停止時の処理を受け入れテストの項目に入れておくと、移行後のトラブルを減らせます。
最後に、原則に合わせること自体を目的にしない姿勢です。原文の例どおりに作ることより、各原則が何を防ぐためのものかを説明でき、今の道具で同じ効果を出せる委託先のほうが、移行後の運用まで任せやすいでしょう。
まとめ:12の原則で確かめたい3つの点
Twelve-Factor Appを実務に生かすうえで、確かめておきたい点は3つです。第一に、設定は環境変数で渡し、コードを今すぐ公開しても認証情報が漏れない状態にすること。第二に、プロセスをステートレスにし、ログは標準出力へ、停止の合図を受けたら処理を終えてから止まる作りにすること。第三に、原文は2017年時点の文書で改訂も途中であることを踏まえ、依存関係や管理プロセスなどは今の道具に置き換えて読むことです。この3点を押さえておけば、コンテナやクラウドへ移すときの手戻りを減らしやすくなります。
よくある質問
Twelve-Factor Appは今でも通用しますか
考え方の多くは今も通用します。設定を環境変数に置く、ログを標準出力へ流す、プロセスをステートレスにするといった原則は、コンテナや管理サービスの前提になっています。ただし原文の最終更新は2017年で、例に挙がる道具には古いものもあるため、例は今の道具に置き換えて読みます。
12の原則をすべて守らないといけませんか
一度にすべてを満たす必要はありません。既存のアプリを移すときは、設定の切り出し、ログの標準出力化、セッションやファイルの置き場の見直しなど、移行先で問題になりやすい因子から手を付けるのが現実的です。後回しにする因子とその理由を記録しておくと、後から判断を見直せます。
秘密情報も環境変数に入れてよいですか
原文は外部サービスの認証情報も設定に含め、環境変数に置くとしています。実務では、値そのものは秘密情報の管理サービスで保管し、起動時に環境変数やファイルとして渡す構成がよく使われます。ログや例外の出力に値が載らないようにすることも欠かせません。
クラウドネイティブなアプリへの移行のご相談
元請(プライムベンダー)として、既存アプリの設計の見直しからコンテナ化、保守・運用までご提案します。
Remoguとリラシクなら、クラウドネイティブなアプリの開発や運用に加わるITエンジニアも探せます。
Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。
出典
- *1 参考:The Twelve-Factor App(公式サイト)(https://12factor.net/)。出典:The Twelve-Factor App 公式サイトのトップページ。方法論の目的、12の因子の一覧、「Last updated 2017」の表示(2026年10月1日確認)を参照。日本語の因子名は同サイトの日本語訳(https://12factor.net/ja/)による(2026年10月確認)
- *2 参考:The Twelve-Factor App「III. Config」(https://12factor.net/config)。出典:設定の定義、コードへの定数書き込みを違反とする記述、公開できるかという判定基準、設定ファイル方式の弱点、名前付きの環境でまとめる方式の問題を参照(2026年10月確認)
- *3 参考:The Twelve-Factor App「VI. Processes」(https://12factor.net/processes)。出典:ステートレスで何も共有しないプロセス、メモリやディスクを一時置き場に限る記述、スティッキーセッションを違反とする記述を参照(2026年10月確認)
- *4 参考:The Twelve-Factor App「IX. Disposability」(https://12factor.net/disposability)。出典:SIGTERMを受けたときのWebプロセスとワーカープロセスの終わり方を参照(2026年10月確認)
- *5 参考:The Twelve-Factor App「XI. Logs」(https://12factor.net/logs)。出典:ログファイルを自ら管理せず、イベントの流れをバッファせずに標準出力へ書くという記述を参照(2026年10月確認)
- *6 参考:twelve-factor/twelve-factor「UPDATE_FAQ.md」(GitHub)(https://github.com/twelve-factor/twelve-factor/blob/main/UPDATE_FAQ.md)。出典:原則と例を切り分けて例を更新する方針、因子の数を12に保つ方針、認証やサービス間通信を課題とする記述を参照(2026年10月確認)
- *7 参考:Heroku「Heroku Open Sources the Twelve-Factor App Definition」(https://www.heroku.com/blog/heroku-open-sources-twelve-factor-app-definition/)。出典:Herokuによるオープンソース化の発表(2024年11月12日)を参照(2026年10月確認)
- *8 参考:The Twelve-Factor Blog「Twelve-Factor App Methodology is now Open Source」(https://12factor.net/blog/open-source-announcement)。出典:2011年にHerokuが最初にまとめた文書を、コミュニティで今の時代に合わせて改めるという説明を参照(2026年10月確認)
- *9 参考:twelve-factor/twelve-factor(GitHub リポジトリ)(https://github.com/twelve-factor/twelve-factor)。出典:README の、改訂版がいずれ12factor.netを置き換えること、変更をnextブランチで進めることの記述を参照。nextブランチの更新日はGitHubのコミット履歴で確認(2026年10月1日)(2026年10月確認)
- *10 参考:Kubernetes Documentation「Secrets」(https://kubernetes.io/docs/concepts/configuration/secret/)。出典:Secretが既定では暗号化されずにetcdに保存されるという注意書きを参照(2026年10月確認)
- *11 参考:Kubernetes Documentation「Pod Lifecycle」(https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/)。出典:Pod終了時のTERMシグナル、terminationGracePeriodSecondsの既定値30秒、猶予後の強制終了の記述を参照(2026年10月確認)