Twelve-Factor App入門|モダンなWebアプリ設計の12原則を解説

kento_morota 11分で読めます

クラウド環境でのアプリケーション開発が当たり前になった現在、「どうすればスケーラブルで運用しやすいアプリケーションを設計できるか」は多くのエンジニアが直面する課題です。

Twelve-Factor Appは、Herokuの共同創業者Adam Wigginsが2012年に提唱した、モダンなWebアプリケーション設計のための12の原則です。提唱から10年以上が経過した今でも、クラウドネイティブ開発のバイブルとして広く参照されています。本記事では、12の原則それぞれの意味と実践的な適用方法を解説します。

Twelve-Factor Appとは?背景と目的

Twelve-Factor Appは、SaaS(Software as a Service)アプリケーションの開発・運用における共通課題を解決するためのメソドロジーです。以下の3つの目的を掲げています。

セットアップの自動化
新しい開発者がプロジェクトに参加する際のコストを最小化します。

OSとの明確な契約
実行環境への依存を最小限にし、移植性を最大化します。

クラウドプラットフォームへの適合
サーバーやシステム管理の手間を最小化し、クラウドネイティブな運用を実現します。

これらの原則は、プログラミング言語やフレームワークに依存しない汎用的なガイドラインです。小規模なWebアプリからエンタープライズシステムまで、幅広いプロジェクトに適用できます。

第1〜3原則:コードベース・依存関係・設定

第1原則:コードベース(Codebase)

「バージョン管理される1つのコードベースと、複数のデプロイ」が原則です。

1つのアプリケーションには、1つのGitリポジトリ(コードベース)が対応します。開発環境、ステージング環境、本番環境はすべて同じコードベースから生成されます。環境ごとにコードを分けることはしません。

実践ポイント
複数のアプリケーションが1つのリポジトリに混在する「モノレポ」の場合でも、各アプリケーションは独立したデプロイ単位として管理しましょう。共有ライブラリは依存関係として管理します。

第2原則:依存関係(Dependencies)

「依存関係を明示的に宣言し、分離する」が原則です。

アプリケーションが必要とするライブラリはすべて、マニフェストファイルで明示的に宣言します。Node.jsならpackage.json、Pythonならrequirements.txt、JavaならMaven/Gradleの設定ファイルがこれに当たります。

システムにグローバルにインストールされたツール(curlやImageMagickなど)に暗黙的に依存してはいけません。必要であれば、Dockerfileやbuildpacksで明示的にインストールします。

実践ポイント
lockファイル(package-lock.json、Pipfile.lockなど)をリポジトリにコミットし、すべての環境で同一バージョンの依存関係を使うようにしましょう。

第3原則:設定(Config)

「設定を環境変数に格納する」が原則です。

データベースのURL、外部APIのキー、ログレベルなど、環境によって異なる値はコードに含めず、環境変数で管理します。これにより、同一のコードベースを設定の変更だけで異なる環境にデプロイできます。

実践ポイント
.envファイルをローカル開発で使う場合は、.gitignoreに追加して絶対にリポジトリにコミットしないこと。本番環境ではクラウドプラットフォームのシークレット管理機能(AWS Secrets Manager、HashiCorp Vaultなど)を活用しましょう。

第4〜6原則:バックエンドサービス・ビルド/リリース/実行・プロセス

第4原則:バックエンドサービス(Backing Services)

「バックエンドサービスをアタッチされたリソースとして扱う」が原則です。

データベース、メッセージキュー、キャッシュ、メール送信サービスなどのバックエンドサービスは、すべて交換可能なリソースとして扱います。ローカルのMySQLをAmazon RDSに切り替える際に、コードの変更なく接続先URLの変更だけで対応できるべきです。

実践ポイント
バックエンドサービスへの接続情報は環境変数で管理し(第3原則と連動)、接続を抽象化するレイヤーを設けましょう。

第5原則:ビルド、リリース、実行(Build, Release, Run)

「ビルド、リリース、実行の3つのステージを厳密に分離する」が原則です。

ビルドステージでは、ソースコードをコンパイルし、依存関係を取得して実行可能なビルド成果物を作成します。リリースステージでは、ビルド成果物に環境固有の設定を組み合わせて、デプロイ可能なリリースを作成します。実行ステージでは、リリースをプロセスとして起動します。

実践ポイント
Dockerを使うと、この分離を自然に実現できます。Dockerイメージのビルド→タグ付け→コンテナの実行という流れがそのまま3つのステージに対応します。CI/CDパイプラインでこの流れを自動化しましょう。

第6原則:プロセス(Processes)

「アプリケーションを1つもしくは複数のステートレスなプロセスとして実行する」が原則です。

各プロセスは状態(ステート)を持たず、永続化が必要なデータはすべてバックエンドサービス(データベースなど)に保存します。セッション情報をプロセスのメモリやローカルファイルに保存してはいけません。

実践ポイント
セッション管理にはRedisやMemcachedなどの外部ストアを使用します。ファイルアップロードはS3などのオブジェクトストレージに保存します。ステートレスにすることで、プロセスの追加・削除によるスケーリングが容易になります。

第7〜9原則:ポートバインディング・並行性・廃棄容易性

第7原則:ポートバインディング(Port Binding)

「ポートバインディングによってサービスを公開する」が原則です。

アプリケーションは、外部のWebサーバー(ApacheやNginx)に依存せず、自身でHTTPポートをバインドしてリクエストを受け付けます。Node.jsのExpressやPythonのFlask/Djangoは、この原則を自然に満たします。

実践ポイント
コンテナ化されたアプリケーションでは、DockerfileのEXPOSE命令でポートを宣言し、アプリケーションがそのポートでリッスンするようにします。リバースプロキシとしてのNginxは、アプリケーションの外部に配置します。

第8原則:並行性(Concurrency)

「プロセスモデルによってスケールアウトする」が原則です。

アプリケーションのスケーリングは、プロセス数を増やすこと(水平スケーリング)で実現します。Webリクエストの処理にはWebプロセス、バックグラウンドジョブにはワーカープロセス、というようにプロセスタイプを分けて管理します。

実践ポイント
Kubernetesのレプリカ数の調整、Amazon ECSのサービスのタスク数変更で、この原則を実践できます。オートスケーリングを設定し、負荷に応じてプロセス数を動的に調整することで、リソースの効率的な利用を実現しましょう。

第9原則:廃棄容易性(Disposability)

「高速な起動とグレースフルシャットダウンにより堅牢性を最大化する」が原則です。

プロセスは、いつでも開始・停止できるように設計します。起動時間は最小化し、停止のシグナルを受けたら処理中のリクエストを完了してから安全に終了します。

実践ポイント
SIGTERMシグナルのハンドリングを実装し、処理中のリクエストの完了、データベース接続のクリーンアップを行ってからプロセスを終了しましょう。KubernetesのterminationGracePeriodSecondsを適切に設定し、グレースフルシャットダウンの猶予時間を確保します。

第10〜12原則:開発/本番一致・ログ・管理プロセス

第10原則:開発/本番一致(Dev/Prod Parity)

「開発、ステージング、本番環境をできるだけ一致させる」が原則です。

環境間のギャップを3つの観点で最小化します。時間のギャップ(開発からデプロイまでの期間を短縮)、人のギャップ(開発者自身がデプロイと運用に関与)、ツールのギャップ(すべての環境で同じバックエンドサービスを使用)です。

実践ポイント
Docker Composeを使ってローカル開発環境を本番に近づけましょう。開発環境でSQLiteを使い本番ではPostgreSQLを使う、といった差異は避けるべきです。CI/CDパイプラインを整備し、コミットから本番デプロイまでの時間を最小化します。

第11原則:ログ(Logs)

「ログをイベントストリームとして扱う」が原則です。

アプリケーションはログの保存やルーティングに関与しません。すべてのログを標準出力(stdout)に出力し、実行環境がログの収集・集約・保存を担当します。

実践ポイント
アプリケーションはconsole.log()や標準出力に構造化ログ(JSON形式)を出力します。コンテナ環境では、Fluentd、Logstashなどのログコレクターが標準出力からログを収集し、Elasticsearch、CloudWatch Logsなどに転送する構成が一般的です。

第12原則:管理プロセス(Admin Processes)

「管理タスクを1回限りのプロセスとして実行する」が原則です。

データベースマイグレーション、一時的なデータ修正、REPLでのデバッグなどの管理タスクは、アプリケーションと同じコードベース・設定・依存関係を使い、ワンオフのプロセスとして実行します。

実践ポイント
Kubernetesではkubectl execやJobリソースを使って管理タスクを実行します。管理用のスクリプトはリポジトリに含め、アプリケーションコードと一緒にバージョン管理しましょう。

Twelve-Factor Appを超えて:現代の追加原則

Twelve-Factor Appが提唱された2012年以降、クラウドネイティブ開発はさらに進化しました。原典の12原則を補完する、現代で重要な追加の観点を紹介します。

API First

サービス間の通信インターフェース(API)を先に設計し、その後に実装を行うアプローチです。OpenAPI(Swagger)などのAPI仕様を先に定義することで、フロントエンドとバックエンドの並行開発が可能になります。

テレメトリ

アプリケーションの健全性を監視するために、メトリクス、ログ、トレースの3つの柱(Three Pillars of Observability)を整備します。PrometheusやGrafana、OpenTelemetryなどのツールを活用して可観測性を確保しましょう。

セキュリティ

ゼロトラストセキュリティの考え方をアプリケーション設計に組み込みます。すべての通信をTLS/SSLで暗号化し、最小権限の原則でサービスアカウントを管理し、シークレットの安全な管理を徹底します。

実践的な導入アプローチ

12の原則すべてを一度に適用する必要はありません。優先度の高いものから段階的に取り入れましょう。

優先度高(すぐに始めるべき)

第2原則(依存関係の明示的宣言)、第3原則(設定の環境変数化)、第1原則(コードベースの管理)は、既存プロジェクトにも比較的容易に適用でき、効果が大きいです。

優先度中(インフラ整備と合わせて)

第5原則(ビルド/リリース/実行の分離)、第10原則(開発/本番一致)、第11原則(ログのストリーム化)は、CI/CDパイプラインやコンテナ環境の整備と合わせて導入すると効果的です。

優先度低(スケーリング要件に応じて)

第6原則(ステートレスプロセス)、第8原則(並行性)、第9原則(廃棄容易性)は、トラフィックの増加やスケーリング要件が生じたタイミングで対応しても十分です。

まとめ

Twelve-Factor Appの12原則は、クラウドネイティブなアプリケーション設計の基盤です。依存関係の明示的管理、設定の外部化、ステートレスなプロセス設計、ログのストリーム化といった原則は、スケーラブルで運用しやすいアプリケーションを構築するための普遍的な指針となっています。

すべてを一度に実現する必要はなく、プロジェクトの状況に応じて段階的に取り入れていくのが実践的です。まずは依存関係の管理と設定の環境変数化から始め、CI/CDの整備やコンテナ化を進める中で、自然と多くの原則に沿った設計になるはずです。

#Twelve-Factor#アプリ設計#クラウドネイティブ
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

起業準備に役立つ情報、もっとありますよ。

まずは話だけ聞いてもらう