コンテナの実行環境をEC2からECS on Fargateへ移行してみた

こんにちは、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側で作り込む必要があります。
    • 移行後: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の制約に合うか事前確認が必要です。