AWS ECS + Fargate を使った Next.js アプリのコンテナデプロイ

---
**ECS + Fargate** を使用してコンテナ化したアプリケーションを AWS 上で管理する方法を説明します。この手順では、Docker イメージを AWS Elastic Container Registry (ECR) にプッシュし、ECS + Fargate を使用してそのイメージを実行する構成を構築します。


## **1. 前提条件**

### **AWS CLI のインストールと設定**
1. **AWS CLI をインストール**
   - [AWS CLI公式サイト](https://aws.amazon.com/cli/)からインストール。
   - バージョン確認:
     ```bash
     aws --version
     ```

2. **AWS CLI を設定**
   - プロファイルを設定します：
     ```bash
     aws configure
     ```
   - AWS アクセスキー、シークレットキー、リージョン（例: `ap-northeast-1`）を入力。

### **Docker のインストール**
- Docker がインストールされていることを確認してください。
  ```bash
  docker --version
  ```

## **2. Docker イメージを作成**

### **1. Dockerfile を用意**
Dockerfileをプロジェクトのルートに作成します。

```dockerfile
# ベースイメージ
FROM node:20-alpine

# 作業ディレクトリを設定
WORKDIR /app

# 依存関係をコピーしてインストール
COPY package.json package-lock.json ./
RUN npm install

# ソースコードをコピー
COPY . .

# アプリケーションをビルド
RUN npm run build

# ポートを公開
EXPOSE 3000

# アプリケーションを起動
CMD ["npm", "start"]
```

### **2. Docker イメージをビルド**
以下のコマンドを使用して Docker イメージをビルドします。

```bash
docker build -t my-next-app .
```

### **3. ローカルでテスト**
イメージをテストするためにローカルでコンテナを起動します。

```bash
docker run -p 3000:3000 my-next-app
```

ブラウザで [http://localhost:3000](http://localhost:3000) を開き、動作確認します。


## **3. Docker イメージを ECR にプッシュ**

### **1. ECR リポジトリの作成**
新しいリポジトリを作成します。

```bash
aws ecr create-repository --repository-name my-next-app
```

### **2. Docker のログイン**
AWS CLI を使用して ECR にログインします。
`<account-id>` → **AWSアカウントID**（12桁の数値）  
`ap-northeast-1` → **利用するAWSリージョン**（例: `us-east-1` や `ap-southeast-1` など） 
```bash
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com
```

### **3. イメージをタグ付け**
Docker イメージを ECR 用にタグ付けします。

```bash
docker tag my-next-app:latest <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/my-next-app:latest
```

### **4. イメージをプッシュ**
ECR にイメージをプッシュします。

```bash
docker push <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/my-next-app:latest
```

## **4. ECS クラスターの作成**

### **1. クラスターを作成**
以下のコマンドで ECS クラスターを作成します。

```bash
aws ecs create-cluster --cluster-name my-cluster
```


## **5. タスク定義を作成**

### **1. タスク定義の JSON ファイルを作成**
`task-definition.json` をプロジェクトのルートディレクトリに作成します。
```json
{
  "family": "my-next-app-task",
  "containerDefinitions": [
    {
      "name": "my-next-app",
      "image": "<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/my-next-app:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000,
          "protocol": "tcp"
        }
      ],
      "memory": 512,
      "cpu": 256,
      "essential": true
    }
  ],
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::<account-id>:role/ecsTaskExecutionRole"
}
```
`<account-id>` → **AWSアカウントID**  
`ap-northeast-1` → **ECRのリージョン**  
`ecsTaskExecutionRole` → **適切なIAMロール名**（デフォルトならそのままでOK）
### **2. タスク定義を登録**
以下のコマンドでタスク定義を登録します。

```bash
aws ecs register-task-definition --cli-input-json file://task-definition.json
```

## **6. ECS サービスを作成**

### **1. サービスを作成**
以下のコマンドで ECS サービスを作成します。

```bash
aws ecs create-service \
  --cluster my-cluster \
  --service-name my-next-app-service \
  --task-definition my-next-app-task \
  --desired-count 1 \
  --launch-type FARGATE \
  --network-configuration 'awsvpcConfiguration={subnets=[subnet-12345678],securityGroups=[sg-12345678],assignPublicIp="ENABLED"}'
```
`subnet-12345678` → **デプロイするVPC内のサブネットID**  
`sg-12345678` → **セキュリティグループID** 

## **7. 動作確認**
### **確認手順**
1. **AWS Management Console** にログイン。
2. **ECS ダッシュボード**を開きます。
3. **該当するクラスター**を選択。
4. **タスクタブ**に移動。
5. 実行中のタスクをクリックし、詳細を確認。
6. **ネットワークインターフェイス (ENI)** に関連付けられた **パブリック IP** を確認。

  ```
  http://<パブリック IP>:3000
  ```
これでアプリケーションが動作していれば完了です。

# **ECSに作成したものの構成要素**

### **1. ECS クラスター**
- **役割**:
  - コンテナを管理する基盤。
  - 1つ以上のタスクまたはサービスをグループ化。
- **今回の構成**:
  - `my-cluster` というクラスターを作成。
  - このクラスターにタスク（コンテナ）を実行する環境を提供。

---

### **2. タスク定義**
- **役割**:
  - **タスク（コンテナの実行単位）** の設定を定義。
  - コンテナイメージ、リソース（CPU、メモリ）、ネットワーク、実行時の環境変数などを指定。
- **今回の構成**:
  - `my-next-app-task` というタスク定義を作成。
  - `my-next-app` というコンテナイメージ（ECR に格納した Docker イメージ）を利用。
  - 必要なメモリや CPU リソースを指定し、ポート `3000` を公開する設定を含む。

---

### **3. ECS サービス**
- **役割**:
  - タスクを自動的に管理し、実行を保証。
  - 指定した数のタスク（コンテナ）が常に動作するように監視・再起動。
  - スケーリング（負荷に応じてコンテナ数を増減）をサポート。
- **今回の構成**:
  - `my-next-app-service` というサービスを作成。
  - 1つのタスクが常に実行されるように設定（`--desired-count 1`）。
  - **Fargate** を利用して、サーバーレス環境でタスクを実行。

---

### **4. ネットワーク構成**
- **役割**:
  - ECS サービス（タスク）が通信するためのネットワーク設定。
  - サブネット、セキュリティグループ、パブリックIPの割り当てなどを管理。
- **今回の構成**:
  - **サブネット**:
    - サービスが実行されるネットワーク範囲。
    - 指定したサブネット内でタスクが実行される。
  - **セキュリティグループ**:
    - タスクに対するインバウンド／アウトバウンド通信を制御。
    - 今回はポート `3000` を公開して外部アクセスを許可。
  - **パブリックIPの割り当て**:
    - サービスにパブリックIPを割り当て、インターネット経由でアクセス可能。

## **まとめ**

### **AWS ECS + Fargate を活用するメリット**
1. **サーバーレス運用（Fargate）**
   - Fargate を利用することで、EC2 のインフラ管理が不要になり、コンテナの運用負担を軽減。
   - サーバーレス環境でスケーラビリティの高いアプリケーションを構築可能。

2. **コスト効率の向上**
   - 必要な分だけリソースを確保し、利用した分だけ課金される。
   - EC2 ベースの ECS に比べ、アイドル時のコストを削減しやすい。

3. **スケーラビリティと可用性**
   - ECS の **Auto Scaling** を活用し、トラフィックの増減に応じて自動でスケール可能。
   - 高負荷時には複数のタスクを実行し、負荷分散が可能。

4. **AWS のセキュリティと統合**
   - **IAM ロール** により、ECR や S3 など AWS の他サービスとの連携が安全に行える。
   - **VPC 内のプライベートサブネット** で実行すれば、よりセキュアな環境構築が可能。

5. **Next.js の最適な運用**
   - Next.js はサーバーサイドレンダリング（SSR）や静的サイト生成（SSG）をサポート。
   - コンテナ化することで、ランタイム環境を統一し、安定したデプロイが可能。

  
**「インフラの管理を減らしつつ、スケールしやすい Next.js アプリをデプロイしたい」** という場合に最適です。

特に、**コスト効率や運用の簡便性** を重視するプロジェクトでは、ECS + Fargate を活用することで **シンプルかつスケーラブルなアプリケーション運用** を実現できます。