ECSとFargateで本格的なWebアプリをデプロイしよう
このハンズオンでは、Docker Composeで3層アーキテクチャを構築しようで構築したノートアプリケーションを、AWSのECS/Fargateにデプロイする方法について実際にハンズオン形式で手を動かしながら体験します。
- ECRへのコンテナイメージのプッシュ
- ALBとターゲットグループの作成
- ECSクラスター、タスク定義、サービスの作成
- オートスケーリングの設定と動作確認
- CloudWatch Logsによるログの確認
1. 事前準備
Gitの基礎知識を習得していることを前提とします。自信のない方は先に以下の講座を実施してください。
このハンズオンでは、以下のツールやアカウントが必要です。まだ準備できていない場合は、リンク先の手順に沿って準備をお願いします。
2. ハンズオンの概要
このハンズオンでは、前の講座で使用したノートアプリケーション(Nginx + FastAPI + MySQL)を、AWSのECS/Fargateにデプロイします。
2.1 APIとデータベース
以下は、API層とデータベース層の構成図です。

ユーザからのリクエストはインターネットゲートウェイ(note-app-igw)を通じてVPC内に入り、パブリックサブネットに配置されたALB(note-app-api-alb)が受け付けます。ALBは、プライベートサブネットに配置されたFargateタスク(APIサーバ)にリクエストを振り分けます。Fargateタスクは2つのアベイラビリティゾーンに分散配置されているため、片方のAZに障害が発生してもサービスを継続できます。
APIサーバは同じプライベートサブネット内のRDS(MySQL)に接続してデータの読み書きを行います。RDSもプライベートサブネットに配置されているため、インターネットから直接アクセスされることはありません。
プライベートサブネット内のFargateタスクは、NATゲートウェイ(note-app-natgw)を経由してECRリポジトリ(note-app-api)からDockerイメージを取得します。
2.2 フロントエンド
以下は、フロントエンド層の構成図です。

フロントエンドもAPI層と同じ構成です。パブリックサブネットに配置されたALB(note-app-front-alb)がユーザからのリクエストを受け付け、プライベートサブネットに配置されたFargateタスク(Webサーバ / Nginx)に振り分けます。
フロントエンドのFargateタスクは、ブラウザに表示するHTML・CSS・JavaScriptを配信します。ブラウザ上のJavaScriptからAPI用ALBのDNS名を通じてAPIサーバにリクエストを送ることで、ノートの作成・取得・更新・削除といった操作を実現します。
2.3 ECS関連
以下は、ECSの論理的な構成を示した図です。

ECSクラスター(note-app-cluster)の中に、フロントエンド用とAPI用の2つのECSサービスを作成します。各ECSサービスは対応するタスク定義に基づいてFargateタスクを起動し、タスク定義はそれぞれのECRリポジトリに格納されたDockerイメージを参照します。
ECSサービスが指定した数のタスクを常時維持するため、タスクが異常終了した場合でも自動的に新しいタスクが起動され、サービスが継続されます。
3. 環境構築
3.1 サンプルリポジトリのクローン
このハンズオンで使用するノートアプリケーションのソースコードは、GitHubのサンプルリポジトリに用意しています。コマンドプロンプト(Windows)またはターミナル(Mac)を開き、任意の場所で以下のコマンドを実行します。
git clone https://github.com/gevanni-academy/sample-note-api.git
クローンが完了したら、Visual Studio Codeを起動し、「ファイル」→「フォルダーを開く」から、クローンしたsample-note-apiフォルダを開いてください。以降の操作は、Visual Studio Codeのターミナルから行います。
3.2 CloudFormationによる環境構築
このハンズオンでは、ECS/Fargateの構築に集中するため、前提となるネットワークやデータベースのリソースはCloudFormationで一括作成します。
| 📝 CloudFormationとは |
|---|
| CloudFormationは、AWSのリソースをテンプレート(YAML/JSON)で定義し、自動的に作成・管理できるサービスです。手動でリソースを一つずつ作成する代わりに、テンプレートをアップロードするだけで必要なリソースをまとめて構築できます。 IaC( Infrastructure as Code)ツールとしてはTerraformも広く使われていますが、Terraformは事前にインストールが必要です。一方、CloudFormationはAWSマネジメントコンソールからそのまま実行できるため、今回のハンズオンではCloudFormationを使用します。なお、このハンズオンではCloudFormationテンプレートの内容を理解する必要はありません。テンプレートをそのままアップロードして環境を構築してください。 |
CloudFormationで作成されるリソースは以下のとおりです。
| リソース | 名前 | 説明 |
|---|---|---|
| VPC | note-app-vpc | 10.0.0.0/16のアドレス範囲を持つ仮想ネットワーク |
| パブリックサブネット | note-app-public-subnet-1, 2 | ALBを配置(2AZ構成) |
| プライベートサブネット | note-app-private-subnet-1, 2 | Fargateタスク・RDSを配置(2AZ構成) |
| インターネットゲートウェイ | note-app-igw | パブリックサブネットからのインターネットアクセス用 |
| NATゲートウェイ | note-app-natgw | プライベートサブネットからECRへのイメージ取得用 |
| ルートテーブル | note-app-public-rtb | パブリックサブネット用のルーティング |
| ルートテーブル | note-app-private-rtb | プライベートサブネット用のルーティング(NATゲートウェイ経由) |
| セキュリティグループ | note-app-alb-sg | ALB用(HTTP:80を許可) |
| セキュリティグループ | note-app-api-sg | APIタスク用(ALBからの8000を許可) |
| セキュリティグループ | note-app-front-sg | フロントタスク用(ALBからの80を許可) |
| セキュリティグループ | note-app-rds-sg | RDS用(APIタスクからの3306を許可) |
| DBサブネットグループ | note-app-db-subnet-group | RDS用のサブネットグループ |
| RDSインスタンス | note-app-db | MySQLデータベース(notedb) |
| 💡 ポイント |
|---|
| Fargateタスクをプライベートサブネットに配置するのは、インターネットからタスクに直接アクセスさせないためのセキュリティ上のベストプラクティスです。ユーザからのアクセスはALB(パブリックサブネット)が受け付け、ALBからプライベートサブネット内のタスクに転送します。 ただし、プライベートサブネット内のタスクはそのままではインターネットに接続できないため、ECRからのDockerイメージの取得が失敗します。これを解決するためにNATゲートウェイを配置し、プライベートサブネットからインターネットへのアウトバウンド通信(外向きの通信)を可能にしています。 このハンズオンではコストを抑えるためゾーナルNATゲートウェイを1つのAZにのみ配置しています。業務ではリージョン全体で共有できるリージョナルNATゲートウェイを使うと構成がシンプルになりますが、リージョン内のAZ数に応じた時間料金がかかるため、コスト要件に応じて使い分けてください。 |
AWSマネジメントコンソールの検索ボックスで「CloudFormation」と入力し、CloudFormationのダッシュボードを開きます。

「スタックの作成」>「新しいリソースを使用(標準)」をクリックします。

スタックの作成の設定を行っていきます。下記表に従い、設定を行ってください。設定後、次へをクリックしてください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| テンプレートの準備 | 既存のテンプレートを選択 | 事前に作成したテンプレートファイルを使用するため |
| テンプレートソース | テンプレートファイルのアップロード | ローカルのテンプレートファイルを直接アップロードするため |
| テンプレートファイルのアップロード | 以下のYAMLテンプレートを保存したファイル | ハンズオン環境を構築するテンプレートを指定するため |
アップロードするのは下記ファイルです。こちらをtemplate.ymlのような任意の名前でローカル環境に保存し、それをアップロードしてください。
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS/Fargate Hands-on Environment (VPC, Security Groups, RDS)
Parameters:
DBMasterPassword:
Type: String
NoEcho: true
Description: Password for RDS master user (admin)
MinLength: 8
Resources:
# ==================== VPC ====================
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: note-app-vpc
# ==================== Subnets ====================
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: ap-northeast-1a
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: note-app-public-subnet-1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: ap-northeast-1c
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: note-app-public-subnet-2
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: note-app-private-subnet-1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: ap-northeast-1c
Tags:
- Key: Name
Value: note-app-private-subnet-2
# ==================== Internet Gateway ====================
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: note-app-igw
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# ==================== Route Table ====================
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: note-app-public-rtb
PublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
# ==================== NAT Gateway ====================
NatGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Tags:
- Key: Name
Value: note-app-natgw-eip
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGatewayEIP.AllocationId
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: note-app-natgw
# ==================== Private Route Table ====================
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: note-app-private-rtb
PrivateRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable
# ==================== Security Groups ====================
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for ALB
GroupName: note-app-alb-sg
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: note-app-alb-sg
APISecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for API tasks
GroupName: note-app-api-sg
VpcId: !Ref VPC
Tags:
- Key: Name
Value: note-app-api-sg
APIFromALBIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref APISecurityGroup
IpProtocol: tcp
FromPort: 8000
ToPort: 8000
SourceSecurityGroupId: !Ref ALBSecurityGroup
FrontSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Front tasks
GroupName: note-app-front-sg
VpcId: !Ref VPC
Tags:
- Key: Name
Value: note-app-front-sg
FrontFromALBIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref FrontSecurityGroup
IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for RDS
GroupName: note-app-rds-sg
VpcId: !Ref VPC
Tags:
- Key: Name
Value: note-app-rds-sg
RDSFromAPIIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref RDSSecurityGroup
IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref APISecurityGroup
# ==================== DB Subnet Group ====================
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupName: note-app-db-subnet-group
DBSubnetGroupDescription: Subnet group for note app RDS
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
# ==================== RDS ====================
RDSInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: note-app-db
Engine: mysql
EngineVersion: '8.0'
DBInstanceClass: db.t3.micro
AllocatedStorage: 20
StorageType: gp2
MasterUsername: admin
MasterUserPassword: !Ref DBMasterPassword
DBName: notedb
DBSubnetGroupName: !Ref DBSubnetGroup
VPCSecurityGroups:
- !Ref RDSSecurityGroup
PubliclyAccessible: false
AvailabilityZone: ap-northeast-1a
Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
PublicSubnet1Id:
Description: Public Subnet 1 ID
Value: !Ref PublicSubnet1
PublicSubnet2Id:
Description: Public Subnet 2 ID
Value: !Ref PublicSubnet2
PrivateSubnet1Id:
Description: Private Subnet 1 ID
Value: !Ref PrivateSubnet1
PrivateSubnet2Id:
Description: Private Subnet 2 ID
Value: !Ref PrivateSubnet2
RDSEndpoint:
Description: RDS Endpoint Address
Value: !GetAtt RDSInstance.Endpoint.Address
ALBSecurityGroupId:
Description: ALB Security Group ID
Value: !Ref ALBSecurityGroup
APISecurityGroupId:
Description: API Security Group ID
Value: !Ref APISecurityGroup
FrontSecurityGroupId:
Description: Front Security Group ID
Value: !Ref FrontSecurityGroup

「次へ」をクリックし、スタックの詳細を設定します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| スタック名 | ecs-handson | ハンズオン用のスタックであることを識別するため |
| DBMasterPassword | 任意のパスワード(8文字以上) | RDSへの接続パスワード。後ほど使用するため控えておくこと |

「次へ」をクリックします。
スタックオプションはデフォルトのまま「次へ」をクリックします。

確認画面で内容を確認し、「送信」をクリックします。

CloudFormationのスタックが作成されます。ステータスがCREATE_IN_PROGRESSとなり、作成中であることがわかります。スタックの作成には10〜15分ほどかかります。

ステータスがCREATE_COMPLETEになれば、リソースの作成が完了です。

3.3 CloudFormation出力値の確認
スタックの詳細画面で「出力」タブをクリックしてください。この後のハンズオンで使用する値が表示されます。以下の表を参考に、各値を控えておいてください。

| キー | 意味 | ハンズオンでの用途 |
|---|---|---|
| VPCId | 作成されたVPCのID | ECSサービス・ALBの作成時にVPCを指定するため |
| PublicSubnet1Id | パブリックサブネット1のID | ALBの配置先として指定するため |
| PublicSubnet2Id | パブリックサブネット2のID | ALBの配置先として指定するため |
| PrivateSubnet1Id | プライベートサブネット1のID | ECSサービスの作成時にタスクの配置先として指定するため |
| PrivateSubnet2Id | プライベートサブネット2のID | ECSサービスの作成時にタスクの配置先として指定するため |
| RDSEndpoint | RDSの接続先ホスト名 | APIコンテナの環境変数(DB_HOST)に設定するため |
| ALBSecurityGroupId | ALB用セキュリティグループのID | ALBの作成時にセキュリティグループを指定するため |
| APISecurityGroupId | APIタスク用セキュリティグループのID | APIのECSサービス作成時にセキュリティグループを指定するため |
| FrontSecurityGroupId | フロントタスク用セキュリティグループのID | フロントのECSサービス作成時にセキュリティグループを指定するため |
また、スタック作成時に指定した DBMasterPassword(RDSのパスワード)も、後でAPIコンテナの環境変数に設定するため控えておいてください。
4. アプリケーション層の構築
FastAPIのAPIサーバをECS/Fargateにデプロイします。
4.1 イメージのビルド
ECS/Fargateでアプリケーションをデプロイするには、まずDockerイメージをビルドする必要があります。Docker Compose環境ではローカルでイメージをビルドしてそのまま使用しましたが、ECS環境ではビルドしたイメージをECRにプッシュし、Fargateがそこからイメージを取得して実行します。
Visual Studio Codeのターミナルからapiフォルダに移動し、Dockerイメージをビルドします。
cd api
docker build --platform linux/amd64 -t note-app-api:v1 .
--platform linux/amd64を指定することで、Fargateで動作するx86_64アーキテクチャのイメージをビルドします。
| 💡 ポイント |
|---|
サンプルリポジトリのmain.pyには、起動時にデータベースのテーブルを自動作成するlifespan関数が含まれています。Docker Compose環境ではinit.sqlでテーブルを作成していましたが、RDSではinit.sqlを自動実行できないため、この仕組みによりAPIコンテナ起動時にテーブルが自動作成されます。RDSの起動直後は接続に失敗することがあるため、最大30回まで2秒間隔でリトライする処理も入っています。 |
4.2 ECRリポジトリの作成

ビルドしたDockerイメージをAWS上で利用するには、イメージを保管する場所が必要です。ECR(Elastic Container Registry)はAWSが提供するDockerイメージのレジストリサービスで、Docker Hubのようにイメージをプッシュ・プルできます。
AWSマネジメントコンソールでECRを開き、サイドメニュー空「プライベートリポジトリ」の部分にある「リポジトリ」をクリックしたうえで、右上の「リポジトリを作成」をクリックします。

下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| リポジトリ名 | note-app-api | APIコンテナを識別するため |
| イメージタグのミュータビリティ | Mutable | デフォルトのまま。イメージタグの上書きを許可するため |
| 暗号化設定 | AES-256 | デフォルトのまま。標準的な暗号化で十分なため |

入力が完了したら「作成」をクリックします。リポジトリ一覧に note-app-api が表示されれば、リポジトリの作成は成功です。

4.3 ECRへのプッシュ
ECRリポジトリが作成できたら、ローカルでビルドしたDockerイメージをECRにプッシュします。ECRにプッシュすることで、ECS/Fargateがこのイメージを取得してコンテナを起動できるようになります。
ECRにログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com
ECRの認証トークンを取得し、Dockerクライアントでログインします。「Login Succeeded」と表示されれば成功です。
タグの付与
docker tag note-app-api:v1 <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-api:v1
ローカルのイメージに、ECRリポジトリのURIをタグとして付与します。Dockerはタグに含まれるURIを見てプッシュ先を判断するため、この手順が必要です。
ECRリポジトリにプッシュ
docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-api:v1
タグ付けしたイメージをECRリポジトリにプッシュします。プッシュが完了すると、ECRコンソール上でイメージを確認できるようになります。

| ⚠️ 「AccessDeniedException」エラーが出る場合 |
|---|
IAMユーザにECRへの権限がありません。IAMコンソールでAmazonEC2ContainerRegistryFullAccessポリシーをアタッチしてください。 |
4.4 ALBとターゲットグループの作成

ECSサービスを作成する前に、トラフィックを振り分けるためのALBとターゲットグループを作成します。今回、Fargateタスクはプライベートサブネットに配置しますが、ALBはインターネットからのアクセスを受け付けるためパブリックサブネットに配置する必要があります。ALBとECSサービスで配置するサブネットが異なるため、ALBはEC2コンソールで事前に作成します。
ターゲットグループの作成
EC2コンソールの「ターゲットグループ」から「ターゲットグループの作成」をクリックします。


下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ターゲットタイプ | IPアドレス | Fargateではインスタンスではなく、タスクごとに割り振られるIPアドレスでルーティングするため |
| ターゲットグループ名 | note-app-api-tg | ターゲットグループを識別するため |
| プロトコル | HTTP | HTTP通信を使用するため |
| ポート | 8000 | FastAPIがリッスンするポート |
| VPC | CloudFormation出力値のVPCIdに対応するVPC |
CloudFormationで作成したVPCを選択 |
| ヘルスチェックパス | /health | FastAPIのヘルスチェックエンドポイントを使用するため |

「次へ」をクリックし、ターゲットの登録はスキップして「次へ」をクリックします。

確認と作成の画面が表示されるので、特に問題がなければ「ターゲットグループの作成」をクリックします。

無事にターゲットグループが作成されれば、ここまでの操作は完了です。

| 💡 ポイント |
|---|
| ターゲットの登録はスキップして構いません。ECSサービスを作成する際にALBとターゲットグループを紐づけると、ECSがタスクの起動・停止に合わせてターゲットの登録・解除を自動的に行います。そのため、ここで手動でターゲットを登録する必要はありません。 |
ALBの作成
EC2コンソールの「ロードバランサー」から「ロードバランサーの作成」を選択してください。

「Application Load Balancer」の「作成」をクリックします。

下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ロードバランサー名 | note-app-api-alb | ALBを識別するため |
| スキーム | インターネット向け | インターネットからアクセスを受け付けるため |
| IPアドレスタイプ | IPv4 | 標準的なIPv4を使用するため |
| VPC | CloudFormation出力値のVPCIdに対応するVPC |
CloudFormationで作成したVPCを選択 |
| マッピング | CloudFormation出力値のPublicSubnet1Id、PublicSubnet2Idに対応するサブネット |
パブリックサブネットを選択(プライベートサブネットを選ばないよう注意) |
| セキュリティグループ | CloudFormation出力値のALBSecurityGroupIdに対応するSG |
CloudFormationで作成したALB用セキュリティグループを選択 |

リスナーの設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| プロトコル | HTTP | HTTPでリクエストを受け付けるため |
| ポート | 80 | 標準的なHTTPポート |
| デフォルトアクション | note-app-api-tgに転送 | 先ほど作成したターゲットグループを選択 |

「ロードバランサーの作成」をクリックします。

ロードバランサー一覧に note-app-api-alb が表示されれば成功です。

4.5 ECSクラスターの作成

ECSクラスターは、コンテナを実行するための論理的なグループです。サービスやタスクはクラスターの中に作成するため、まずクラスターを用意する必要があります。
ECSコンソールを開き、サイドメニューから「クラスター」を選択し、右上の「クラスターの作成」をクリックします。

下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| クラスター名 | note-app-cluster | クラスターを識別するため |
| インフラストラクチャ | Fargateのみ | サーバレスで運用するため |

無事にnote-app-clusterが作成されればここまでの操作は完了です。なお、作成までには数分かかることがあります。

4.6 タスク定義の作成

タスク定義は、コンテナの設計図にあたるものです。使用するDockerイメージ、割り当てるCPU・メモリ、環境変数、ポート設定などを定義します。Docker Composeの docker-compose.yml に相当する役割です。
「タスク定義」→「新しいタスク定義の作成」をクリックします。

下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスク定義ファミリー | note-app-api | タスク定義を識別するため |
| 起動タイプ | AWS Fargate | サーバレスで実行するため |
| オペレーティングシステム | Linux/X86_64 | 一般的なLinux環境を使用するため |
| タスクサイズ - CPU | 1 vCPU | 最小限のリソースで十分なため |
| タスクサイズ - メモリ | 3 GB | 最小限のリソースで十分なため |
| タスク実行ロール | 新しいロールの作成 | ECRからイメージを取得するために必要 |

| 💡 ポイント |
|---|
タスク実行ロールは、ECSがコンテナを起動する際に使用するIAMロールです。「新しいロールの作成」を選択すると、ecsTaskExecutionRole という名前のロールが自動的に作成され、ECRからのイメージ取得やCloudWatch Logsへのログ出力に必要な権限が付与されます。このロールは一度作成されると、次回以降のタスク定義では「既存のロールを使用」から ecsTaskExecutionRole を選択できるようになります。 |
| 💡 ポイント |
|---|
| 同じ画面にあるタスクロールは未選択のままで構いません。タスクロールは、コンテナ内のアプリケーションからS3やDynamoDBなどのAWSサービスにアクセスする場合に必要となるロールです。今回のアプリケーションはRDSへの接続にIAMロールを使用しないため(環境変数でユーザ名・パスワードを直接指定するため)、タスクロールは不要です。 |
コンテナの設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| 名前 | api | コンテナを識別するため |
| イメージURI | <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-api:v1 | ECRにプッシュしたイメージ |
| コンテナポート | 8000 | FastAPIがリッスンするポート |

環境変数
Docker Compose環境では、docker-compose.yml の environment セクションでデータベースの接続先を指定していました。ECS環境でも同じように、タスク定義の環境変数でAPIコンテナにRDSの接続情報を渡します。アプリケーションのコード内で os.environ などを使ってこれらの値を読み取り、RDSに接続します。
| キー | 値 | 設定の基準 |
|---|---|---|
| DB_HOST | CloudFormation出力値のRDSEndpoint |
RDSに接続するため |
| DB_USER | admin | RDSのマスターユーザ名 |
| DB_PASSWORD | スタック作成時に指定したDBMasterPassword |
RDSのマスターパスワード |
| DB_NAME | notedb | 使用するデータベース名 |

| 💡 ポイント |
|---|
| 実務では、パスワードなどの機密情報は環境変数に直接記載せず、AWS Secrets Managerを使用することを推奨します。このハンズオンでは簡略化のため、環境変数に直接設定しています。 |
すべての入力が完了したら、「作成」をクリックします。

無事にタスクが作成されれば、ここまでの操作は完了です。

4.7 ECSサービスの作成

続いて、ECSサービスを作成します。ECSサービスは、タスク定義に基づいてコンテナを起動・維持する仕組みです。指定した数のタスクを常時稼働させ、タスクが停止した場合は自動的に再起動します。
ECSコンソールでクラスターを選択し、「サービス」タブから「作成」をクリックします。

サービスの詳細
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスク定義ファミリー | note-app-api | 先ほど作成したタスク定義を選択 |
| タスク定義のリビジョン | 空欄のまま | 最新リビジョンが自動的に使用されるため |
| サービス名 | note-app-api-service | サービスを識別するため |

環境
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| 既存のクラスター | note-app-cluster | 先ほど作成したクラスターが選択されていることを確認 |
| コンピューティングオプション | キャパシティプロバイダー戦略 | デフォルトのまま |
| キャパシティプロバイダー | FARGATE | Fargateで実行するため |
| プラットフォームバージョン | LATEST | 最新のFargateプラットフォームを使用するため |

デプロイ設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| スケジューリング戦略 | レプリカ | デフォルトのまま。クラスター全体で必要な数のタスクを配置するため |
| 必要なタスク | 1 | まずは1つのタスクで起動する |
| アベイラビリティゾーンのリバランスを有効にする | チェックあり | デフォルトのまま。タスクをAZ間で均等に配置するため |
| ヘルスチェックの猶予期間 | 0 | デフォルトのまま |

ネットワーキング
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| VPC | note-app-vpc |
CloudFormationで作成したVPCを選択 |
| サブネット | note-app-private-subnet-1, note-app-private-subnet-2 |
CloudFormation出力値のPrivateSubnet1Id、PrivateSubnet2Idに対応する2つのプライベートサブネットを選択 |
| セキュリティグループ | note-app-api-sg |
CloudFormation出力値のAPISecurityGroupIdに対応するSG |
| パブリックIP | オフ | プライベートサブネットに配置するためパブリックIPは不要 |

ロードバランシング
「ロードバランシングを使用」にチェックを入れると、ALBの設定項目が表示されます。下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ロードバランサーの種類 | Application Load Balancer | HTTP/HTTPSのルーティングを行うため |
| コンテナ | api 8000:8000 | タスク定義で設定したコンテナとポートを選択 |
| Application Load Balancer | 既存のロードバランサーを使用 | 先ほど作成したALBを使用するため |
| ロードバランサー | note-app-api-alb | 先ほど作成したALBを選択 |
| リスナー | 既存のリスナーを使用 | 先ほど作成したリスナーを使用するため |
| リスナーのポート | 80:HTTP | 先ほど作成したリスナーを選択 |
| ターゲットグループ | 既存のターゲットグループを使用 | 先ほど作成したターゲットグループを使用するため |
| ターゲットグループ名 | note-app-api-tg | 先ほど作成したターゲットグループを選択 |

サービスの自動スケーリング - オプション
アクセスが集中してCPU使用率が高くなった際に、タスク数を自動的に増やして負荷を分散させるための設定を行います。ここでは、CPU使用率が70%を超えたらタスクを追加し、負荷が下がったらタスクを減らすルールを設定します。
「サービスの自動スケーリングを使用」にチェックを入れると、スケーリングの設定項目が表示されます。下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスクの最小数 | 1 | 最低1つは常時起動するため |
| タスクの最大数 | 3 | 負荷に応じて最大3つまでスケールするため |
| スケーリングポリシータイプ | ターゲットの追跡 | メトリクスの目標値に基づいてタスク数を自動調整するため |
| ポリシー名 | api-cpu-scaling | スケーリングポリシーを識別するため |
| ECSサービスメトリクス | ECSServiceAverageCPUUtilization | CPU使用率を監視するため |
| ターゲット値 | 70 | CPU使用率が70%を超えたらスケールアウトするため |
| スケールアウトクールダウン期間 | 300 | デフォルトのまま。スケールアウト後、次の判定まで300秒待機する |
| スケールインクールダウン期間 | 300 | デフォルトのまま。スケールイン後、次の判定まで300秒待機する |
| スケールインをオフにする | チェックなし | デフォルトのまま。負荷が下がったらタスクを減らすため |

すべての設定が完了したら「作成」をクリックします。

サービスが作成中になります。完了まで数分かかるため、しばらく待ちましょう。

| ⚠️ タスクがPENDINGのままになる場合 |
|---|
| (1)セキュリティグループでアウトバウンド通信(すべてのトラフィック)が許可されているか確認してください。 (2)サブネットがプライベートサブネットになっているか確認してください。パブリックサブネットを選択している場合は、プライベートサブネットに変更してください。 (3)タスク定義の環境変数(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)が正しいか確認してください。 |
4.8 動作確認
サービスのステータスが「アクティブ」にり、デプロイとタスクが「1/1件の実行中のタスク」となったら、サービスの作成と、タスクの起動が完了です。

ALB経由でアクセスして動作を確認します。
EC2コンソールの「ロードバランサー」から note-app-api-alb を選択し、「DNS名」をコピーします。ブラウザまたはcurlで以下のようにアクセスしてください。

curl http://<ALBのDNS名>/health
以下のレスポンスが返れば、APIは正常に動作しています。
{"status":"healthy"}
ノート一覧も確認します。
curl http://<ALBのDNS名>/notes
空の配列 [] が返れば、RDSとの接続も成功しています。
| ⚠️ 「502 Bad Gateway」エラーが出る場合 |
|---|
(1)ターゲットグループでターゲットが「healthy」になっているか確認してください。ターゲットが「unhealthy」の場合は、ヘルスチェックパスが /health に設定されているか確認してください。(2)APIタスク用セキュリティグループで、ALBのセキュリティグループからのポート8000へのインバウンドが許可されているか確認してください。 |
4.9 CloudWatch Logsでログを確認
ECSで動作するコンテナのログは、ローカル環境のように docker logs コマンドでは確認できません。代わりに、CloudWatch Logsでログを確認します。
ECSコンソールでクラスターを選択し、note-app-api-service をクリックします。「ログ」タブを開くと、コンテナの標準出力がCloudWatch Logsに記録されているのを確認できます。
ログにはFastAPIの起動メッセージや、APIへのリクエストのアクセスログが表示されています。先ほど curl でアクセスした /health や /notes へのリクエストが記録されていることを確認してください。

ログを確認すると、自分がアクセスした覚えのない /health へのリクエストが一定間隔で記録されていることに気づくかもしれません。これは、ALBが自動的に行っているヘルスチェックのリクエストです。ALBはターゲットグループに設定されたヘルスチェックパス(今回は /health)に対して定期的にリクエストを送り、タスクが正常に動作しているかを監視しています。タスクから正常なレスポンスが返らない場合、ALBはそのタスクへのトラフィック転送を自動的に停止します。
| 💡 ポイント |
|---|
| CloudWatch Logsは、ECS上のコンテナのトラブルシューティングに欠かせないツールです。タスクが起動に失敗した場合や、アプリケーションでエラーが発生した場合は、まずCloudWatch Logsを確認してください。実務では、エラーログを検知してSlackやメールに通知する仕組みを構築するのが一般的です。 |
4.10 オートスケーリングの動作確認
ECSサービスの作成時にオートスケーリングを設定しましたが、ここではタスク数を手動で変更して、スケールアウト(タスクの増加)の動作を実際に確認します。
ECSコンソールでサービスを選択し、「サービスを更新」をクリックします。

「必要なタスク」の値を 1 から 2 に変更して「更新」をクリックしてください。

しばらくすると、「タスク」タブに2つのタスクが表示されます。両方のタスクのステータスが「実行中」になれば、スケールアウトが完了です。

EC2コンソールでターゲットグループ note-app-api-tg を開き、「ターゲット」タブを確認してください。2つのターゲットが「healthy」として登録されていることがわかります。ALBは、これら2つのタスクにリクエストを自動的に分散します。

| 💡 ポイント |
|---|
| 今回はタスク数を手動で2に変更しましたが、ECSサービスの作成時に設定したオートスケーリングにより、CPU使用率が70%を超えた場合は自動的にタスクが追加されます。逆に負荷が下がればタスクは自動的に削減されます。 また、「必要なタスク」を 0 に変更するとすべてのタスクが停止し、ALBにアクセスしても「503 Service Unavailable」が返るようになります。メンテナンス時にタスクを一時的に停止させたい場合などに利用できます。 |
5. プレゼンテーション層の構築
NginxのフロントエンドをECS/Fargateにデプロイします。手順はアプリケーション層と同様ですので、重複する説明は省略します。
5.1 ソースコードの修正
Docker Compose環境では、フロントエンドとAPIは同じマシン上で動作していたため、script.js のAPI接続先は http://localhost:8000 でした。しかし、ECS環境ではフロントエンドとAPIはそれぞれ別のFargateタスクとして独立して動作しており、localhost ではAPIにアクセスできません。そこで、API接続先をAPI用ALBのDNS名に変更することで、フロントエンドからALB経由でAPIにリクエストを送る構成にします。
Visual Studio Codeのエクスプローラーから front/script.js を開いてください。ファイルの1行目に以下のような記述があります。
const API_URL = 'http://localhost:8000';
この http://localhost:8000 の部分を、先ほど作成したAPI用ALBのDNS名に変更します。ALBのDNS名は、EC2コンソールの「ロードバランサー」から note-app-api-alb を選択して確認できます。
const API_URL = 'http://<API用ALBのDNS名>';
変更したら、ファイルを保存してください。
| 💡 ポイント |
|---|
ローカル環境ではhttp://localhost:8000でAPIに接続していましたが、ECS環境ではフロントエンドとAPIが別々のタスクで動作するため、API用ALBのDNS名を指定する必要があります。 |
5.2 イメージのビルドとプッシュ
API層と同じ手順で、フロントエンドのDockerイメージをビルドし、ECRにプッシュします。
イメージのビルド
Visual Studio Codeのターミナルで front フォルダに移動します。API層のビルド時に api フォルダにいる場合は、以下のコマンドで移動してください。
cd ../front
現在のディレクトリが front フォルダであることを確認します。
Macの場合:
pwd
Windowsの場合:
cd
どちらの場合も、表示されたパスの末尾が front になっていれば正しいディレクトリにいます。以下のコマンドでイメージをビルドします。
docker build --platform linux/amd64 -t note-app-front:v1 .
ECRリポジトリの作成

ECRコンソールでフロント用のリポジトリを作成します。API層と同じ手順で「リポジトリを作成」をクリックし、下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| リポジトリ名 | note-app-front | フロントコンテナを識別するため |
| イメージタグのミュータビリティ | Mutable | デフォルトのまま |
| 暗号化設定 | AES-256 | デフォルトのまま |

入力が完了したら「作成」をクリックします。リポジトリ一覧に note-app-front が表示されれば成功です。

タグの付与
docker tag note-app-front:v1 <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-front:v1
ローカルのイメージに、ECRリポジトリのURIをタグとして付与します。
ECRリポジトリにプッシュ
docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-front:v1
プッシュが完了したら、ECRコンソールで note-app-front リポジトリにイメージが登録されていることを確認してください。

5.3 ALBとターゲットグループの作成

API層と同様に、フロントエンド用のALBとターゲットグループをEC2コンソールで作成します。
ターゲットグループの作成
EC2コンソールの「ターゲットグループ」から「ターゲットグループの作成」をクリックします。下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ターゲットタイプ | IPアドレス | Fargateではインスタンスではなく、タスクごとに割り振られるIPアドレスでルーティングするため |
| ターゲットグループ名 | note-app-front-tg | ターゲットグループを識別するため |
| プロトコル | HTTP | HTTP通信を使用するため |
| ポート | 80 | Nginxがリッスンするポート |
| VPC | CloudFormation出力値のVPCIdに対応するVPC |
CloudFormationで作成したVPCを選択 |
| ヘルスチェックパス | / | ルートパスで応答確認 |

「次へ」をクリックし、ターゲットの登録はスキップして「次へ」をクリックします。

「ターゲットグループの作成」をクリックします。

無事にターゲットグループが作成されれば、ここまでの操作は成功です。

ALBの作成
EC2コンソールの「ロードバランサー」から「ロードバランサーの作成」→「Application Load Balancer」の「作成」をクリックします。

下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ロードバランサー名 | note-app-front-alb | ALBを識別するため |
| スキーム | インターネット向け | インターネットからアクセスを受け付けるため |
| IPアドレスタイプ | IPv4 | 標準的なIPv4を使用するため |
| VPC | CloudFormation出力値のVPCIdに対応するVPC |
CloudFormationで作成したVPCを選択 |
| マッピング | CloudFormation出力値のPublicSubnet1Id、PublicSubnet2Idに対応するサブネット |
パブリックサブネットを選択 |
| セキュリティグループ | CloudFormation出力値のALBSecurityGroupIdに対応するSG |
CloudFormationで作成したALB用セキュリティグループを選択 |

リスナーの設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| プロトコル | HTTP | HTTPでリクエストを受け付けるため |
| ポート | 80 | 標準的なHTTPポート |
| デフォルトアクション | note-app-front-tgに転送 | 先ほど作成したターゲットグループを選択 |

「ロードバランサーの作成」をクリックします。

ロードバランサー一覧に note-app-front-alb が表示されれば成功です。

| 💡 ポイント |
|---|
本来であれば、APIとフロントエンドは1つのALBにまとめ、リスナールールで振り分けるのが一般的です。たとえば、独自ドメインを取得して api.example.com はAPIへ、app.example.com はフロントエンドへ振り分けるホストベースルーティングが代表的な方法です。ただし、この方法には独自ドメインの取得が必要になります。今回のハンズオンではドメインの取得は行わないため、APIとフロントエンドでそれぞれ別のALBを作成しています。ALBが2つになることでコストは増えますが、ハンズオンの手順をシンプルに保つことを優先しています。 |
5.4 タスク定義の作成

API層と同様に、フロントエンド用のタスク定義を作成します。「タスク定義」→「新しいタスク定義の作成」をクリックし、下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスク定義ファミリー | note-app-front | タスク定義を識別するため |
| 起動タイプ | AWS Fargate | サーバレスで実行するため |
| タスクサイズ - CPU | 1 vCPU | 最小限のリソース |
| タスクサイズ - メモリ | 3 GB | 最小限のリソース |

コンテナの設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| 名前 | front | コンテナを識別するため |
| イメージURI | <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/note-app-front:v1 | ECRにプッシュしたイメージ |
| コンテナポート | 80 | Nginxがリッスンするポート |

すべて入力が終わったら「作成」をクリックします。

無事にタスク定義が作成されれば、ここまでの操作は完了です。

5.5 ECSサービスの作成

API層と同様の手順で、フロントエンド用のECSサービスを作成します。クラスターは既存のnote-app-clusterを使用します。「サービス」タブから「作成」をクリックし、下記の内容を設定してください。
サービスの詳細
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスク定義ファミリー | note-app-front | 作成したタスク定義を選択 |
| タスク定義のリビジョン | 空欄のまま | 最新リビジョンが自動的に使用されるため |
| サービス名 | note-app-front-service | サービスを識別するため |

環境
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| 既存のクラスター | note-app-cluster | API層と同じクラスターが選択されていることを確認 |
| コンピューティングオプション | キャパシティプロバイダー戦略 | デフォルトのまま |
| キャパシティプロバイダー | FARGATE | Fargateで実行するため |
| プラットフォームバージョン | LATEST | 最新のFargateプラットフォームを使用するため |

デプロイ設定
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| スケジューリング戦略 | レプリカ | デフォルトのまま |
| 必要なタスク | 1 | 最小構成 |
| アベイラビリティゾーンのリバランスを有効にする | チェックあり | デフォルトのまま |
| ヘルスチェックの猶予期間 | 0 | デフォルトのまま |

ネットワーキング
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| VPC | CloudFormation出力値のVPCIdに対応するVPC |
CloudFormationで作成したVPCを選択 |
| サブネット | CloudFormation出力値のPrivateSubnet1Id、PrivateSubnet2Idに対応するサブネット |
2つのプライベートサブネットを選択 |
| セキュリティグループ | CloudFormation出力値のFrontSecurityGroupIdに対応するSG |
フロントタスク用SG |
| パブリックIP | オフ | プライベートサブネットに配置するためパブリックIPは不要 |

ロードバランシング
「ロードバランシングを使用」にチェックを入れ、下記の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| ロードバランサーの種類 | Application Load Balancer | HTTP/HTTPSのルーティングを行うため |
| コンテナ | front 80:80 | タスク定義で設定したコンテナとポートを選択 |
| Application Load Balancer | 既存のロードバランサーを使用 | 先ほど作成したALBを使用するため |
| ロードバランサー | note-app-front-alb | 先ほど作成したALBを選択 |
| リスナー | 既存のリスナーを使用 | 先ほど作成したリスナーを使用するため |
| リスナーのポート | 80:HTTP | 先ほど作成したリスナーを選択 |
| ターゲットグループ | 既存のターゲットグループを使用 | 先ほど作成したターゲットグループを使用するため |
| ターゲットグループ名 | note-app-front-tg | 先ほど作成したターゲットグループを選択 |

サービスの自動スケーリング - オプション
API層と同様に設定します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| タスクの最小数 | 1 | 最低1つは常時起動するため |
| タスクの最大数 | 4 | 負荷に応じて最大4つまでスケールするため |
| スケーリングポリシータイプ | ターゲットの追跡 | メトリクスの目標値に基づいてタスク数を自動調整するため |
| ポリシー名 | front-cpu-scaling | スケーリングポリシーを識別するため |
| ECSサービスメトリクス | ECSServiceAverageCPUUtilization | CPU使用率を監視するため |
| ターゲット値 | 70 | CPU使用率が70%を超えたらスケールアウトするため |

すべての設定が完了したら「作成」をクリックします。
note-app-front-serviceのステータスが「アクティブ」となり、デプロイとタスクが「1/1 件の実行中のタスク」となれば、ここまでは成功です。
5.6 動作確認
フロント用ALBのDNS名を確認し、ブラウザで開きます。
http://<フロント用ALBのDNS名>
無事にノートアプリが起動することを確認します。

APIとの接続もできているかを確認するため、タイトルと内容に任意の値を入力し、「追加」をクリックします。

入力した項目がノート一覧に表示されれば、APIとの連携もできているため、ここまでは成功です。

6. 不要リソースの削除
ハンズオンが終わったら、課金を避けるため、作成したリソースを削除します。以下の順序で削除してください。
6.1 ECSサービスの削除
ECSコンソールでクラスターを選択し、2つのサービス(api、front)を削除します。「強制削除」オプションを使用すると、タスクも同時に停止されます。
6.2 ECSクラスターの削除
サービスが削除されたら、クラスターを削除します。
6.3 タスク定義の登録解除
2つのタスク定義(note-app-api、note-app-front)を登録解除します。
6.4 ALBの削除
EC2コンソールで2つのALB(api、front)を削除します。
6.5 ターゲットグループの削除
2つのターゲットグループを削除します。
6.6 ECRリポジトリの削除
ECRコンソールで2つのリポジトリ(note-app-api、note-app-front)を削除します。
6.7 CloudFormationスタックの削除
CloudFormationコンソールでecs-handsonスタックを選択し、「削除」をクリックします。VPC、セキュリティグループ、RDSなど、CloudFormationで作成したすべてのリソースが自動的に削除されます。
| 💡 ポイント |
|---|
スタックの削除には10分程度かかります。ステータスがDELETE_COMPLETEになるまで待ってください。RDSの削除に時間がかかるため、削除中にエラーが表示された場合は数分待ってから再度削除を実行してください。 |
7. まとめ
このハンズオンでは、ノートアプリケーションをECS/Fargateにデプロイする方法を体験しました。
- ECRにAPIとフロントエンドのDockerイメージをプッシュした
- ALBとターゲットグループを作成し、パブリックサブネットに配置してインターネットからのアクセスを受け付けた
- ECSクラスターを作成し、タスク定義に基づいて2つのサービス(API、フロント)をプライベートサブネットにデプロイした
- CloudWatch Logsでコンテナのログを確認し、ALBのヘルスチェックログについても学んだ
- タスク数を手動で変更して、スケールアウトの動作を確認した
8. 次のステップ
これでコンテナ講座は最後の講座まで完了です。学んだ内容を実際の成果物に落とし込みたい方は、章末尾の応用課題に挑戦してみてください。タスク管理APIをコンテナ化し、Docker Compose でローカル起動した上で、ECS/Fargate にデプロイする課題です。
応用課題の課題内容は誰でも閲覧できます。メンターによる成果物レビューや実装の壁打ちはポートフォリオプランでご提供しています。