Github→AWS ECR→ECSのCICDをすべてterraformで管理するまで

# 初めに
本プロジェクトはchatGPTと対話しながら進めました
nextjsをwebに公開する一連の流れを記録した備忘録になります
これ以降は対話した内容をchatGPTにまとめてもらったものです
大分つたないものなので要望があればちゃんと書きます

## 1. Next.js プロジェクトを作成し、GitHub にプッシュ

まず、Next.js のプロジェクトを作成し、それを GitHub にプッシュします。

### 1.1 Next.js プロジェクトの作成
```sh
npx create-next-app my-app
cd my-app
```

### 1.2 GitHub リポジトリの作成とプッシュ
```sh
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-username/next_test.git
git push -u origin main
```

## 2. Terraform を使用して AWS 環境を構築

Terraform を使って AWS のインフラをコード化し、ECS 上で Next.js を動かす環境を作ります。

### 2.1 AWS CLI の設定
AWS の CLI をインストールし、認証情報を設定します。
```sh
aws configure
```

### 2.2 ネットワークの構築 (`network.tf`)
ECS を動作させるための VPC、サブネット、NAT ゲートウェイを設定します。

#### **VPC の作成**
```hcl
resource "aws_vpc" "my_app_vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_support = true
  enable_dns_hostnames = true
  tags = { Name = "my-app-vpc" }
}
```

#### **パブリック / プライベートサブネットの作成**
```hcl
resource "aws_subnet" "my_app_subnets" {
  count = 2
  vpc_id = aws_vpc.my_app_vpc.id
  cidr_block = "10.0.${count.index}.0/24"
  availability_zone = element(["ap-northeast-1a", "ap-northeast-1c"], count.index)
  map_public_ip_on_launch = count.index == 0 ? true : false
  tags = { Name = "my-app-subnet-${count.index}" }
}
```

#### **NAT ゲートウェイの作成**
```hcl
resource "aws_eip" "my_app_nat_eip" { domain = "vpc" }
resource "aws_nat_gateway" "my_app_nat_gw" {
  allocation_id = aws_eip.my_app_nat_eip.id
  subnet_id = aws_subnet.my_app_subnets[0].id
}
```

#### **ルートテーブルの設定**
```hcl
resource "aws_route_table" "my_app_private_rt" {
  vpc_id = aws_vpc.my_app_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.my_app_nat_gw.id
  }
}
```

### 2.3 ECS クラスターの作成 (`ecs.tf`)
```hcl
resource "aws_ecs_cluster" "my_app_ecs_cluster" {
  name = "my-app-ecs-cluster"
}
```

### 2.4 ALB の設定 (`alb.tf`)
```hcl
resource "aws_lb" "my_app_alb" {
  name               = "my-app-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.my_app_sg.id]
  subnets            = aws_subnet.my_app_subnets[*].id
}
```

## 3. CodePipeline を使用してビルドとデプロイを自動化
GitHub の変更をトリガーに、ECR にコンテナをプッシュし、ECS にデプロイされるようにします。

### 3.1 CodePipeline の設定 (`codepipeline.tf`)
```hcl
resource "aws_codepipeline" "my_app_codepipeline" {
  name     = "my-app-codepipeline"
  role_arn = aws_iam_role.my_app_codepipeline_role.arn
  artifact_store {
    location = aws_s3_bucket.my_app_pipeline_artifacts.bucket
    type     = "S3"
  }
}
```

### 3.2 CodeBuild の `buildspec.yml`
ECR へのビルドとプッシュ、ECS の更新を行います。
```yaml
phases:
  pre_build:
    commands:
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REPOSITORY
  build:
    commands:
      - docker build -t my-app .
      - docker tag my-app:latest $ECR_REPOSITORY:latest
  post_build:
    commands:
      - docker push $ECR_REPOSITORY:latest
      - aws ecs update-service --cluster my-app-ecs-cluster --service my-app-service --force-new-deployment
```

## 4. デプロイの確認
ALB の URL にアクセスし、Next.js の画面が表示されることを確認します。
```sh
aws ecs describe-services --cluster my-app-ecs-cluster --services my-app-service --query 'services[*].loadBalancers[*].{DNSName:dnsName}' --output table
```

## 5. トラブルシューティングと学び

このプロジェクトを進める中で、いくつかの大きな課題に直面しました。

### **5.1 403 Forbidden エラー (ECR のプル失敗)**
ECS が ECR からイメージを取得しようとした際に `403 Forbidden` が発生。

**原因:** NAT ゲートウェイの未設定により、プライベートサブネットのタスクが ECR にアクセスできなかった。

**解決策:**
- NAT ゲートウェイを追加し、適切なルートテーブル設定を行うことで、ECS タスクが ECR へアクセスできるように修正。

### **5.2 ALB のターゲットグループのヘルスチェックが失敗 (502 Bad Gateway)**
ALB から ECS のタスクにリクエストを送った際に `502 Bad Gateway` が発生。

**原因:**
- タスク定義で `containerPort` の設定が不足していた。
- Next.js のアプリが `0.0.0.0` ではなく `localhost` で起動されていた。

**解決策:**
- ECS タスク定義に `containerPort: 80` を追加。
- `next.config.js` を修正し、適切なポートバインドを行う。

---

## まとめ
AWS ECS Fargate に Next.js アプリケーションを Terraform を使ってデプロイすることができました！ 🎉

次のステップとして、
- CodeDeploy を組み込んでブルーグリーンデプロイを試す
- CloudWatch Logs の統合を強化する
- ALB のヘルスチェック設定を最適化する

を試すと、より安定した運用ができるようになります！ 🚀