「オンプレのアプリをそのままコンテナに入れたら、スケールしない・設定管理が地獄になった・ログが追えない」――クラウド移行でこういった問題に直面したことはないでしょうか。
クラウドネイティブなアプリを設計するには、オンプレ時代の「当たり前」を一度リセットする必要があります。その指針となるのが 12ファクターアプリ(The Twelve-Factor App)です。
この記事では、12ファクターの全体像と特に重要なファクターを、オンプレ経験者の視点で解説します。AWSでの実装例も交えながら、実務に直結する形でまとめています。
なぜ12ファクターが必要なのか?オンプレ開発との根本的な違い
オンプレのアプリケーションは、「1台の物理サーバーに常駐する」ことを前提に設計されていることがほとんどです。設定ファイルはサーバー上のローカルパスに置き、ログはローカルファイルに書き出し、セッション情報はプロセスのメモリに保持する。これがオンプレの「普通」でした。
しかしクラウドでは前提が変わります。
・EC2インスタンスやコンテナはいつでも入れ替わる(Immutable Infrastructure)
・オートスケールで複数インスタンスが並列稼働する
・Blue/Greenデプロイで新旧が瞬間的に切り替わる
この環境に「オンプレ設計のアプリ」を持ち込むと、設定がサーバーごとにバラバラになる、スケールアウト時にセッションが切れる、コンテナが終了するたびにログが消えるといった問題が発生します。
12ファクターアプリは、2011年にHerokuの開発者たちが提唱した設計原則です。当初はSaaS開発向けでしたが、コンテナ・Kubernetes・クラウドネイティブ時代のアプリ設計指針として現在も広く参照されています。
12ファクターアプリの全体像
| 番号 | ファクター名 | 一言まとめ |
|---|---|---|
| I | Codebase(コードベース) | 1リポジトリ、複数環境へデプロイ |
| II | Dependencies(依存関係) | 依存ライブラリを明示的に宣言・分離 |
| III | Config(設定) | 設定は環境変数で渡す |
| IV | Backing Services(バックエンドサービス) | DBやキューを「差し替え可能なリソース」として扱う |
| V | Build, Release, Run(ビルド・リリース・実行) | 3ステージを厳密に分離する |
| VI | Processes(プロセス) | アプリはステートレスなプロセスとして動く |
| VII | Port Binding(ポートバインド) | サービスをポートにバインドして公開 |
| VIII | Concurrency(並行性) | プロセスを増やして水平スケール |
| IX | Disposability(廃棄可能性) | 高速起動・グレースフルシャットダウン |
| X | Dev/Prod Parity(開発・本番同一性) | 開発・ステージング・本番を限りなく揃える |
| XI | Logs(ログ) | ログはイベントストリームとして扱い、ファイルに書かない |
| XII | Admin Processes(管理タスク) | DBマイグレ等の管理作業は1回限りのプロセスで実行 |
全12ファクターの中でも、オンプレ経験者が移行時に特につまずきやすい6つを重点的に解説します。
特に重要な6つのファクター詳解
1. 設定を環境変数に格納する(Factor III: Config)
オンプレ時代の典型例は、DBの接続先やAPIキーを application.properties や config.ini に直書きし、サーバーに置いておくパターンです。
クラウドでは、そのファイルを持ったコンテナイメージを本番にそのまま使うと情報漏洩のリスクがあり、環境ごとにイメージを作り直す手間も生じます。
12ファクターでは、設定は 環境変数 で渡します。コードとビルド成果物(イメージ)は環境に依存せず、実行時に環境変数で振る舞いを変えます。
# AWSでの実装例: ECSタスク定義でAWS Secrets Managerから認証情報を渡す # (AWS CLIでタスク定義を確認する場合) aws ecs describe-task-definition --task-definition myapp # タスク定義のsecretsフィールド(JSON) { "secrets": [ { "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:myapp/db-password" }, { "name": "API_KEY", "valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/myapp/api-key" } ] }
AWSでは AWS Secrets Manager や AWS Systems Manager Parameter Store に認証情報を格納し、ECSタスク定義やLambdaの環境変数に紐付けるのが標準的な実装です。
2. アプリをステートレスなプロセスとして実行する(Factor VI: Processes)
オンプレでよくあるのが、「ユーザーセッションをアプリサーバーのメモリに保持」するパターンです。ロードバランサーにスティッキーセッションを設定して特定のサーバーに固定するわけです。
これはオートスケール・Blue/Greenデプロイの天敵です。スティッキーが外れた瞬間にセッションが切れ、ユーザーがログアウトされます。
解決策は、セッション情報をプロセス外の共有ストアに逃がすことです。
・セッション → Amazon ElastiCache(Redis) または Amazon DynamoDB
・一時ファイル → Amazon S3 または Amazon EFS
・状態を持つ処理 → Amazon SQS等のキューに分離
プロセスがどのインスタンスで動いても同じ結果を返せる設計が「ステートレス」の本質です。
3. バックエンドサービスを差し替え可能なリソースとして扱う(Factor IV: Backing Services)
DBやメールサーバー、キューなどの外部サービスを「差し替え可能なアタッチされたリソース」として扱います。コードは特定のDBに依存せず、URLや接続文字列(=環境変数)を変えるだけで切り替えられる設計が理想です。
例えば、開発環境でローカルのMySQLを使い、本番ではAmazon RDSを使う場合、コードの変更ゼロで切り替えられるべきです。さらに、本番障害時にAmazon Aurora Serverlessへ切り替えるといった判断も素早くできます。
オンプレ時代に特定のDBサーバーへのハードコード接続が習慣化していたチームは、ここで設計を根本から見直す必要があります。
4. 高速起動とグレースフルシャットダウン(Factor IX: Disposability)
クラウドではインスタンスが突然終了します(スポットインスタンスの中断、オートスケールのスケールイン、Kubernetesのローリングアップデート等)。
「廃棄可能性」とは、プロセスがいつ終了しても問題ない設計にしておくことです。
・高速起動: 起動に数分かかるアプリは、スケールアウト時に需要に追いつくまで時間がかかりすぎる。目標は数秒以内
・グレースフルシャットダウン: SIGTERMを受け取ったら処理中のリクエストを完了させてから終了する
・冪等性: 強制終了されても再実行で問題が出ない設計にする
ECSでのグレースフルシャットダウンは、タスク定義の stopTimeout を適切に設定し、アプリ側でSIGTERMハンドラーを実装することで実現します。
5. ログをイベントストリームとして扱う(Factor XI: Logs)
オンプレのアプリは /var/log/myapp/access.log のようなファイルにログを書き、logrotateでローテーションするのが一般的でした。
クラウド・コンテナ環境では、コンテナが終了するとファイルは消えます。複数インスタンスのログを個別のサーバーに入って確認するのも非現実的です。
12ファクターでは、アプリはログを標準出力(stdout)に書き出すだけにします。収集・保管・分析は実行環境のインフラ層(ECSのログドライバー、Kubernetes Fluentd等)に任せます。
・AWSでの実装: ECSタスク定義で awslogs ログドライバーを設定 → Amazon CloudWatch Logsに集約
・ログの検索・アラートはCloudWatch Logs Insightsで一元管理
・長期保管はAmazon S3にエクスポートしてAmazon Athenaで分析
6. 開発・ステージング・本番を限りなく揃える(Factor X: Dev/Prod Parity)
「開発環境では動いたのに本番で動かない」という問題は、オンプレ時代に誰もが経験したはずです。OSのバージョン違い、ミドルウェアの設定差異、ライブラリのバージョン不一致――これが「本番との乖離」です。
12ファクターは3つのギャップの縮小を求めます。
・時間のギャップ: デプロイを頻繁に行い、開発と本番の差分を小さく保つ
・人のギャップ: 開発者がデプロイまで責任を持つ(DevOpsカルチャー)
・ツールのギャップ: 開発・本番で同一のミドルウェア・バージョンを使う
コンテナ(Docker)はこのギャップを劇的に縮小します。開発者のPCと本番ECSが同じDockerイメージを動かすことで、「うちの環境では動いた」問題をほぼ排除できます。
AWSで12ファクターを実装するサービス対応表
| ファクター | AWSでの実装手段 | オンプレ相当 |
|---|---|---|
| Config(設定) | AWS Secrets Manager / SSM Parameter Store + ECS/Lambda 環境変数 | 設定ファイル(application.properties等) |
| Processes(ステートレス) | Amazon ElastiCache(Redis)でセッション外部化 | アプリサーバーのメモリ内セッション |
| Backing Services | Amazon RDS / SQS / ElastiCache を環境変数で接続 | 固定IPのDBサーバーへのハードコード接続 |
| Build, Release, Run | AWS CodePipeline + Amazon ECR(イメージをリリース成果物として管理) | サーバー上でgit pullして手動再起動 |
| Disposability | ECSタスクの stopTimeout 設定 + SIGTERMハンドリング | 手動での計画的シャットダウン |
| Logs | ECS awslogs ドライバー → Amazon CloudWatch Logs | ローカルファイル + logrotate |
| Dev/Prod Parity | Docker + Amazon ECR でイメージを共通化 | 開発・本番でOS・ミドルウェアが異なる |
| Admin Processes | ECS RunTask(1回限りのタスク)でDBマイグレーション実行 | サーバーにSSHしてSQLを手動実行 |
よくある違反パターンとオンプレ移行時のつまずき
実際のクラウド移行現場でよく見る「12ファクター違反」のパターンを整理します。
1. 設定ファイルをコンテナイメージに焼き込む
Dockerfileの中で COPY config/production.properties /app/config/ のように設定ファイルをイメージに含めるパターンです。環境ごとにイメージを作り直すことになり、「1つのイメージを複数環境で使う」原則に反します。環境変数または外部の設定ストアに切り出しましょう。
2. ローカルディスクに永続データを書き込む
アプリがコンテナのローカルファイルシステムに一時ファイルやアップロードファイルを保存するパターンです。コンテナが終了するとデータが消え、複数インスタンスで同一ファイルを参照することもできません。Amazon S3やAmazon EFSに外部化するのが正解です。
3. スティッキーセッションへの依存
ALBのスティッキーセッション設定でとりあえず動かすのは「応急処置」であり、スケールアウトの恩恵を受けられません。Amazon ElastiCache(Redis)でセッションを外部化し、どのインスタンスでもリクエストを処理できる設計にしましょう。
4. 起動時間が長すぎる
Javaアプリで起動に2分かかるものをオートスケール対象にしても、急増する需要に追いつくまでに時間がかかりすぎます。起動時間の短縮は12ファクターの重要なKPIです。GraalVM Native ImageやAWS Lambda SnapStartのような仕組みも検討に値します。
5. 管理タスクをアプリのコードに混在させる
DBマイグレーションや初期データ投入の処理をアプリの起動シーケンスに組み込むパターンは危険です。複数インスタンスが同時起動した際に競合が発生します。ECS RunTaskを使い、デプロイパイプラインの中で1回限りのタスクとして実行する設計が正解です。
本記事のまとめ
12ファクターアプリの要点を振り返ります。
・Config(設定): 設定は環境変数へ。コードとイメージは環境に依存しない
・Processes(ステートレス): セッションや状態はElastiCache等に外部化
・Backing Services: DBやキューは「差し替え可能なリソース」として扱う
・Disposability: 高速起動・グレースフルシャットダウンで廃棄可能な設計に
・Logs: ログはstdoutへ。収集はインフラ層(CloudWatch Logs等)に委ねる
・Dev/Prod Parity: コンテナでイメージを共通化し、本番との乖離を最小化
オンプレ時代の「当たり前」を一つひとつ見直すことが、クラウドネイティブなアプリへの第一歩です。既存アプリを全部書き直す必要はありません。まずはConfig(環境変数化)とLogs(stdout化)から始めると、移行の手応えを感じやすいです。
Linuxサーバーの基礎(プロセス管理・ファイルシステム・systemdのグレースフルストップ等)については、姉妹サイトLinuxMaster.JPで詳しく解説しています。
12ファクターの原則、自分のアプリに当てはめてみましたか?
「オンプレアプリをクラウドに移行したい」「コンテナ化したいがどこから手をつければいいかわからない」――そんな現場の悩みに答えるノウハウを、毎週メルマガでお届けしています。
オンプレの経験を活かしながら、現場で使えるクラウドスキルを体系的に身につけたい方へ、メルマガで実践的なクラウド活用ノウハウをお届けしています。
