こんにちは、kanazawaです。
EC2上でDockerを直接動かしてコンテナを管理している場合、インスタンスの管理やDockerのアップデート、複数コンテナの運用など、インフラ側の管理コストが大きくなりがちです。
そこで今回は、EC2 + Dockerの構成から、コンテナの実行環境をECS on Fargateへ移行する手順を実践します。
目次
1. 概要
- 本記事では、EC2 + Dockerの構成からECS on Fargateへの移行手順を実践します。
- 本記事はアプリ改修ではなく、コンテナの実行基盤(運用対象)をEC2→Fargateへ移すことに焦点を当てます。
- アプリケーションにはnginxの公式イメージを使用し、ECS Execによるコンテナへの接続確認も行います。
2. 構成
移行前
EC2 + Dockerの構成は以下の通りです。

- 本構成は検証用の簡易的な構成です。EC2インスタンスをパブリックサブネットに直接配置しています。
- Docker上でnginxコンテナを起動します。
- コンテナの起動・停止・更新はすべてEC2インスタンス上で手動で行います。
移行後
ECS on Fargateの構成は以下の通りです。

- VPC内をパブリックサブネットとプライベートサブネットに分け、ALBをパブリックサブネット、ECSをプライベートサブネットに配置します。
- 接続経路は2つあります。一般ユーザーからのアクセスはインターネットゲートウェイ・ALBを経由してECSに転送されます。アプリチームなどがコンテナ内で作業する場合はCloudShellからECS Execを使用して接続します。
- 外部へのアウトバウンド通信(ECRからのイメージpullなど)はNATゲートウェイを経由します。VPCエンドポイントでも構いません。
3. 移行前環境の構築
それでは、まず移行前のEC2 + Dockerの構成で環境を構築します。
VPCやEC2の作成方法などについては省略します。
EC2のOSは最新のAmazonLinux 2023を選びました。
3-1. Dockerのインストール
- EC2にSSH接続後、以下のコマンドでDockerをインストールして起動します。
dnf update -y dnf install -y docker systemctl start docker systemctl enable docker systemctl status docker usermod -aG docker ec2-user docker --version
※usermodコマンド実行後は再度ログインしなおす方が確実です。
3-2. nginxコンテナの起動
- 公式のnginxイメージを使用してコンテナを起動します。
docker run -d -p 80:80 --name nginx nginx:latest
3-3. 動作確認
- ブラウザからEC2インスタンスのパブリックIPにアクセスし、nginxのデフォルトページが表示されることを確認します。

4. 移行後環境の構築
ECS on Fargate構成を作成していきます。
事前に、サブネットやNATゲートウェイの作成は済んでいます。
4-1. IAMロールの作成
以下の2つのIAMロールを作成します。
①タスク実行ロール
ECSがタスクを起動する際に使用するロールです。コンテナイメージのpull(Docker Hub 等)やCloudWatch Logsへのログ送信に必要です。
| 設定項目 | 設定値 |
|---|---|
| 信頼されたエンティティ | ecs-tasks.amazonaws.com |
| ポリシー | AmazonECSTaskExecutionRolePolicy |
②タスクロール
タスク内のコンテナが使用するロールです。ECS Execの利用に必要です。
| 設定項目 | 設定値 |
|---|---|
| 信頼されたエンティティ | ecs-tasks.amazonaws.com |
| ポリシー | 以下をインラインポリシーで追加 |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
}
4-2. セキュリティグループの作成
以下の2つのセキュリティグループを作成します。
①ALB用SG
| 種別 | プロトコル | ポート | ソース |
|---|---|---|---|
| インバウンド | HTTP | 80 |
0.0.0.0/0 |
※自分のみがアクセスできるようにするなど、必要に応じてIPは絞ってください。
②ECSタスク用SG
| 種別 | プロトコル | ポート | ソース |
|---|---|---|---|
| インバウンド | HTTP | 80 |
ALB用SG |
4-3. ALB・ターゲットグループの作成
以下の設定でALBとターゲットグループを作成します。作成手順は省略します。
| リソース | 設定項目 | 設定値 |
|---|---|---|
| ALB | スキーム | インターネット向け |
| ALB | サブネット | パブリックサブネット |
| ALB | セキュリティグループ | ALB用SG |
| ターゲットグループ | ターゲットタイプ | IP |
| ターゲットグループ | プロトコル | HTTP:80 |
4-4. ECSクラスターの作成
以下の設定でECSクラスターを作成します。
| 設定項目 | 設定値 |
|---|---|
| クラスター名 | 任意 |
| インフラストラクチャ | Fargateのみ |
4-5. タスク定義の作成
以下の設定でタスク定義を作成します。
| 設定項目 | 設定値 |
|---|---|
| 起動タイプ | Fargate |
| OS | Linux/X86_64 |
| CPU | 1 vCPU |
| メモリ | 3GB |
| タスク実行ロール | 上記で作成したタスク実行ロール |
| タスクロール | 上記で作成したタスクロール |
| コンテナイメージURL | nginx:latest |
| コンテナポート | 80 |
4-6. ECSサービスの作成
以下の設定でECSサービスを作成します。
| 設定項目 | 設定値 |
|---|---|
| 起動タイプ | Fargate |
| タスク定義ファミリー | 上記で作成したタスク定義 |
| タスク定義のリビジョン(必要なタスク数) | 1 |
| サブネット | プライベートサブネット |
| セキュリティグループ | ECSタスク用SG |
| パブリックIP | オフ |
| ロードバランサー | 上記で作成したALB |
以下のオプションからECS EXECを有効化することが可能です。

4-7. ECS Execによる接続
サービス作成後、CloudShellから以下のコマンドでコンテナに接続します。
aws ecs execute-command \ --cluster <クラスター名> \ --task <タスクID> \ --container <コンテナ名> \ --interactive \ --command "/bin/bash"
最も簡単な方法として、マネジメントコンソールの対象クラスターから「タスク」タブを開き、タスクをクリックしてコンテナ一覧まで開くと「接続」と表示されています。こちらをクリックするか、CLIコマンドをコピーする方法をお勧めします。

接続に成功すると以下が表示されます。
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. Starting session with SessionId: ecs-execute-command-bioalf4nvsdfcgfvl6thibcize This session is encrypted using AWS KMS.
接続後、コンテナ内でコマンドが実行できることを確認します。
# date Tue Jun 9 15:00:07 UTC 2026 # # # cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 13 (trixie)" NAME="Debian GNU/Linux" VERSION_ID="13" VERSION="13 (trixie)" VERSION_CODENAME=trixie DEBIAN_VERSION_FULL=13.5 ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
4-8. 動作確認
ブラウザからALBのDNS名にアクセスし、nginxのデフォルトページが表示されることを確認します。
まとめ
管理・運用面の違い
- ホスト管理
- 移行前(EC2 + Docker):OS更新、Docker更新、ディスク枯渇対応、障害時の復旧など、ホスト自体の運用が必要になります。
- 移行後(ECS on Fargate):ホスト管理が不要になり、インフラ側の運用負荷を大きく減らせます。
- デプロイ/更新
- 移行前:EC2にSSH接続をして
docker run/docker stopなどの手作業が増えると、手順ミスが発生するリスクが増えます。 - 移行後:タスク定義を更新してサービスを更新すると、ECSがタスクを順番に入れ替えてくれるため、EC2に入って手作業で更新するより楽になるかと思われます。
- 移行前:EC2にSSH接続をして
- 監視・メトリクス
- 移行前:ログ収集やメトリクスの設計をEC2側で作り込む必要があります。
- 移行後:CloudWatch Logsなどと組み合わせやすく、標準機能で実装可能です。
- 接続/保守作業
- 移行前:SSHでEC2に入り作業します(鍵管理や踏み台などの考慮も必要です)。
- 移行後:ECS Execでコンテナへ接続できます(ただし権限設計や監査ログの方針は必要です)。
構成面の違い
- 移行前:EC2がアプリ実行環境そのものになりやすく、1台に責務が寄りがちです。
- 移行後:ALB + ECS(Service/Task)+(必要に応じてNAT/VPCエンドポイント)と役割分担が明確になり、ネットワーク・権限・監視を分離して設計しやすくなります。
注意点 / Tips
- 本記事は「アプリ移行」ではなく「コンテナ実行環境の移行」が主題のため、アプリ差分で悩まないように公式イメージを使用しましたが、実運用では、ECR利用、ログ設計、オートスケール、HTTPS(ACM)などを追加で検討する必要があるでしょう。
- Fargate は Compute Savings Plansの適用や、Fargate Spotによる割引が可能ですが、リザーブドインスタンス(RI)は利用できません。
- ECS on FargateではEC2のように「OSにエージェントを入れる」「任意のデーモンを常駐させる」といったことができないため、自由度は下がります。
- タスクのCPU/メモリの組み合わせ、エフェメラルストレージ容量、起動方式、特定機能の制限など、EC2より選択肢が少ない場面があります。使いたい構成がFargateの制約に合うか事前確認が必要です。




