【AWS編】Next.js × Go × AWSでJWT認証付きGraphQLアプリとCI/CDを構築してみよう

# はじめに

:::note info
■ご案内■
本連載の背景/作成できるアプリケーション/進め方をご理解頂く上でも[【環境構築編】](https://qiita.com/WebEngrChild/items/d4bc23bf352e7aa46361)をご一読頂けると幸いです。

- [【環境構築編】](https://qiita.com/WebEngrChild/items/d4bc23bf352e7aa46361)　
- [【Next.js編】](https://qiita.com/WebEngrChild/items/6e9e3232046301879089)
- [【Go編】](https://qiita.com/WebEngrChild/items/d9b87944235c5220ae5b)
- **[【AWS編】](https://qiita.com/WebEngrChild/items/ca93783f8ae6bee7f985)** 　👈いまここです

これからも頑張ってハンズオン系の記事を書いていきたいと思っているので、いいねっと思って頂けたら**LGTM**押していただけると励みになります！

:::

ここからは実際にアプリケーションをAWSへデプロイしていきます。
本記事では、プロビジョニングツールとしてCloudformationを利用しています。

:::note alert
注意点
利用するAWSの各リソースは課金対象となるものが多く含まれています。個人利用される方は特に注意してください。発生した費用に関して一切責任を負いかねます。
:::

また、本記事で用いる`.yml`ファイルは以下のリポジトリに格納しているので、適宜クローンをお願いします。

https://github.com/WebEngrChild/aws-cloudformation-templates

# 構成図

![Qiita.drawio (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/7e8ae510-bb06-44d5-cf59-2740118be4bd.png)

# リソース紹介

まず最初に、簡単ではありますが、本デプロイフロー(CI/CD)で利用する、主要なAWSリソースを紹介していきます。

:::note warn
本記事では、これまで説明したアプリケーションをAWSにデプロイすることのみに留めています。従って、各種設定ファイルの細かい説明は割愛しているのでご承知おきください。
:::

## ECS

Amazon ECS (Elastic Container Service)は、スケーラブルで高速なコンテナオーケストレーションサービスです。ユーザーは、アプリケーションのデプロイ、スケーリング、管理を簡単に行うことができます。

また、AWS Fargateは、サーバーレスのコンテナ実行環境で、インフラストラクチャの管理を気にせずにアプリケーションをビルド、デプロイ、スケールすることができます。

https://aws.amazon.com/jp/ecs/

https://aws.amazon.com/jp/fargate/

## ECR

Amazon ECR (Elastic Container Registry)は、Dockerコンテナイメージを簡単に保存、管理、デプロイできるフルマネージド型のコンテナレジストリサービスです。

https://aws.amazon.com/ecr/

## CodePipeline

AWS CodePipelineは、連続的インテグレーション (CI) と連続的デリバリー (CD) サービスです。また、同リソース内でCodeBuild, CodeDeploy等と連携することができます。

https://aws.amazon.com/jp/codepipeline/

## CodeBuild

AWS CodeBuildは、ソースコードのコンパイル、テストの実行、アーティファクトのパッケージ化を行うフルマネージドのビルドサービスです。

本記事では、このリソース内でDockerイメージのビルドとECRへのプッシュ、さらにhadolint/Dockle/trivyといった脆弱性診断ツールも実行しています。

また、Go製のマイグレーションツールであるGooseを用いたマイグレーションも実行しています。

https://aws.amazon.com/jp/codebuild/

## Codedeploy

AWS CodeDeployは、アプリケーションの更新を自動化するデプロイサービスで、新しい機能のリリース、アップデートのバグ修正、アプリケーションの稼働時間を最大化します。

また、AWS CodeDeployを使用してECSでブルーグリーンデプロイメントを実行すると、新旧のアプリケーションバージョンを平行して実行でき、最小限のダウンタイムで安全に更新が可能です。

https://aws.amazon.com/jp/codedeploy/

https://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html#welcome-deployment-overview

## RDS

Amazon RDS (Relational Database Service)は、スケーリングとメンテナンスが容易なマネージドリレーショナルデータベースサービスです。MySQL, PostgreSQL, Oracleなど複数のデータベースエンジンをサポートしています。

本記事では、MySQLを利用しています。

https://aws.amazon.com/rds/

## AWS Systems Manager Parameter Store

AWS Systems Manager パラメータストアは、機密情報を安全に保存し、暗号化して管理するサービスです。データベース接続文字列やパスワードなどの機密情報をセキュアに管理できます。

https://aws.amazon.com/jp/systems-manager/features/#Parameter_Store

# 事前準備

上述の通り、本記事ではIaCとしてCloudformationを利用します。
AWSのマーネージメントコンソールから、同ツールを使ってスタックをアップロードする前に事前設定を行っていきます。

また、これまでの記事で紹介した通り、
ご自身のGitHubRepositoryに以下２つのプロジェクトがプッシュされている必要があります。

`go-graphql-jwt-api`
`next-graphql-front`

## IAM作成

:::note warn
既にAWSマネージメントコンソールにログインでき、同様の権限が付与されているIAMユーザーをお持ちの方はスキップして頂いて構いません。
:::

以下の記事等を参考にrootに近い管理者権限を持つユーザーを作成してください。

既にIAMユーザーをお持ちでマネージメントコンソールにログインできる方は、ポリシーを付与するだけでも問題ありません。

https://www.idaten.ne.jp/portal/page/out/secolumn/multicloud/column009.html

二つのポリシーがアタッチされていることを確認してください。
- IAMUserChangePassword
- AdministratorAccess

## AWS CLIインストール

:::note warn
既にAWS CLIがローカルマシンにインストールされている方はスキップして頂いて構いません。
:::

本記事では以下目的でAWS CLIを利用します。
- ローカルマシンから踏み台EC2経由でRDSにssh接続
- ECRに初期イメージをプッシュ

以下の記事などを参考に設定を行ってください。

https://dev.classmethod.jp/articles/aws-cli_initial_setting/

## ドメイン登録とSSL/TLS認証書作成

- **Route53**
    - ドメイン登録(有料)を参考にドメインを作成してください。
    - 本リポジトリでは以下のような形でサブドメインを利用することを想定しています。
        - フロント：`front.example.com`
        - API：`api.example.com`
    - 各レコード/サブドメインの作成と転送先のALBとの紐付けは後述します。

https://blog.serverworks.co.jp/route53-domain-registration#%E6%96%B0%E8%A6%8F%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AE%E7%99%BB%E9%8C%B2%E6%89%8B%E9%A0%86

- **ACMを使ったSSL/TLS認証書発行**
    - 本アプリケーションはhttpsでの通信を行います。
    - 以下の記事を参考に作成したドメインに紐づけく証明書を発行してください。
    - `2-1. AWS Certificate ManagerでSSL/TLS認証書をリクエスト`の箇所だけで大丈夫です。

https://dev.classmethod.jp/articles/lim-aws-certificate-manager/

## EC2（RDSへの踏み台）へのSSH接続用のキーペア作成

Amazon Web Services（AWS）におけるキーペアは、EC2インスタンス（仮想サーバー）への安全なアクセスを行うために必要になります。本記事では、当該EC2は、RDSへSSH接続するための踏み台サーバーとしての役割を担います。

- **キーペア作成方法**
    - AWSコンソール > EC2 > キーペア > キーペアを作成 
    - .pemファイルをローカルマシンにダウンロード

![スクリーンショット 2023-05-25 6.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/1bc59dae-72df-6941-8d3c-3b60ab02f4cb.png)

- **ローカルマシンでのペアキーの許可設定**

ダウンロードしたキーを`~/.ssh/`配下に移動して、適切な権限に変更します。

```sh
$ mv ~/Downloads/db-access-key.pem ~/.ssh
$ chmod 400 ~/.ssh/db-access-key.pem
```

:::note warn
**ご注意**
今回は簡単のため, SSH接続でEC2経由でRDSへ接続しています。一方で、Session Managerを利用すると、これまでのようにEC2インスタンスにパブリックIP経由でSSH接続せずとも色々と作業ができるのでおすすめです。
:::

https://dev.classmethod.jp/articles/try-port-forwarding-with-ssm/

# Cloudformationを使ったスタックアップロード

事前準備が完了したので、ここからは実際にAWSの各リソースを構築していきます。

Cloudformationは、Amazon Web Services（AWS）が提供するインフラストラクチャー管理サービスの1つです。

本リソースを使用することで、AWSリソース（EC2インスタンス、VPC、S3バケットなど）のプロビジョニングや管理を簡単に行うことができます。

上述の通り、本記事では以下のリポジトリに当該ファイルが格納されています。

https://github.com/WebEngrChild/aws-cloudformation-templates

## vpc.yml（共通）

- Cloudformation > スタック > スタックの作成 > 新しいリソースを使用(標準)
- 以下の画像を参考に”ファイルの選択”/common/vpc.ymlを選択
- スタックの詳細を指定 > 各項目に表示されているデフォルのままで変更せずOK
    - ネットワークのCIDRが既存の設計と競合する場合は適宜修正してください。
- スタックの名前は識別できる任意のもの
- スタックオプションの設定 > 設定不要
- 次へ > 送信
- スタックに表示されているステータスが”CREATE_COMPLETE”になれば完了

![cfn使い方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/14508c2e-78cd-0195-2cca-daa8844ef074.png)
![スクリーンショット 2023-05-11 7.04.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/f126ebb1-af23-1d17-a672-778de3a66406.png)
![スクリーンショット 2023-05-07 11.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/2a37f962-e2a0-5de5-37db-707727da5a8b.png)

## ecr.yml（API・フロント計２種構築）
- 上記と同様な手順で`/api/ecr.yml`をアップロード
- スタックの詳細を指定 > 各項目に表示されているデフォルのままで変更せずOK。
- スタックの名前は識別できる任意のもの（フロントとAPIが区別できるように）。
    - ex.api-ecr
- System Configuration
    - Environment
        - デフォルト表示のままでOK

### ローカル環境でDocker imageのビルドと脆弱性チェック

本記事で作成しているCICDでは、Dockerfileの静的解析とDockerイメージの脆弱性チェックとして、以下のツールを利用しています。

- hadolint
- Dockle
- trivy

また、各リポジトリの`README.md`に実行用のコマンドを記載しています。

下記は`go-graphql-jwt-api`のサンプル例になります。

コマンド実行は、`go-graphql-jwt-api`と`next-graphql-front`のディレクトリ配下で実行してください。

**Docker Build**

- 本番ターゲットを指定して実行
- ECSで実行できるようにプラットフォーム指定

```sh:/go-graphql-jwt-api/README.md
# go-graphql-jwt-api
$ docker build --no-cache --target runner -t api-dev-repo --platform linux/amd64 -f ./build/docker/go/Dockerfile .
```

#### **hadolint**

Hadolintは、Dockerfileの静的解析ツールであり、Dockerfileの構文、構造、効率に関するベストプラクティスに従っているかどうかをチェックします。

実行後に何も表示されなければOKです。

```sh:/go-graphql-jwt-api/README.md
$ brew install hadolint
$ hadolint --ignore DL3018 build/docker/go/Dockerfile
```

:::note warn
本記事では、読者の方の正常動作を担保するため、ライブラリのバージョンを固定するルールを無効化しています。ただし、Dockerfileでパッケージをインストールする際には、通常、特定のバージョンを指定することが推奨されます。
:::

https://github.com/hadolint/hadolint

#### **Dockle**

主にDockerイメージのベストプラクティスに焦点を当てた軽量のコンテナイメージスキャナです。

※本記事の設定では一旦、`warn`と`info`は無視しています。

https://github.com/goodwithtech/dockle

```sh:/go-graphql-jwt-api/README.md
$ brew install goodwithtech/r/dockle
$ dockle api-dev-repo
```

#### **trivy**

Trivyは、脆弱性スキャナであり、Dockerイメージおよびファイルシステムに存在するセキュリティ上の脆弱性を検出することに特化しています。

実行後に、`Total: 0 (CRITICAL: 0)`が表示されていればOKです。

https://github.com/aquasecurity/trivy

```sh:/go-graphql-jwt-api/README.md
$ brew install aquasecurity/trivy/trivy
$ trivy image --severity CRITICAL --ignore-unfixed api-dev-repo
```

### ECRに初期イメージプッシュ
- コンソール > Amazon ECR > リポジトリ > api-dev-repoに遷移
- プッシュコマンドを表示
- ローカルマシンで下記画像のうち、それぞれ1 ~ 4のコマンドを実行
- ただし、2.の`docker build`のみ上記で実行済みなので対応不要
- プッシュ後にリポジトリにイメージが登録されていればOK

![スクリーンショット 2023-05-07 11.56.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/0f1345d2-086a-76a5-540b-589c8b33831e.png)

![api-dev-repo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/ddfa5756-6519-0f73-20f3-0a82c88d739d.png)

![プッシュコマンドの表示_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/da8c3e61-13f2-1132-0a72-2fe616fb5d46.png)

![api-dev-repo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/b4126c27-c70a-436f-87da-400a9dd517f0.png)

### フロント用のECR構築
- 同様の手順でフロントアプリケーション用のECRも構築&pushする。
- 設定ファイルは/front/ecr.yml

![スクリーンショット 2023-05-07 12.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/114f08b8-caa8-541f-29b6-793e99aa1acf.png)

### Systems Managerへ環境変数登録

- マネージメントコンソール > Systems Manager > パラメータストア > パラメータを作成
- 設定方法は以下の画像を参考にしてみてください。

￼![スクリーンショット 2023-05-07 13.46.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/f01b956c-52f5-6298-a8b9-a0d30eeb92d1.png)

以下の画像を参考にAWSアカウントに紐づいているECRのドメイン部分をコピーしてください。

|転記元  |SSMでのキー|値|
|---|---|---|
|ECRのドメイン部分  |ECR_REPOSITORY_DOMAIN|xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com|

![スクリーンショット 2023-05-07 16.13.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/074d7021-3e4d-d1f9-e235-54c2564c9f99.png)

## ecs.yml（API ・フロント計２種構築）

### Systems Managerへ環境変数登録

手順は既にECR作成時に設定した内容と全く同じです。

- **API**
    - ディレクトリに格納されている`.env`の内容のうち”必須”と”本番環境時に指定”と記載されている内容を参考に、それぞれパラメーターストアに一つずつ登録してください。

```
# 必須
API_ENV=dev
API_FRONT_URL=https://front.example.com
API_DB_HOST=xxxxxxxx.rds.amazon.com
API_DB_NAME=golang
API_DB_USER=user
API_DB_PASS=password
API_DB_PORT=3306
API_SENTRY_DSN=https://xxxxxxxx.ingest.sentry.io/xxxxxxxx

# 本番環境時に指定
API_APP_DOMAIN=https://api.example.com
```

- **フロント**
    - .env.localを参考に作成

```
NEXT_PUBLIC_API_URL=https://api.example.com
```

### スタックアップロード

- 上記と同様な手順で/api/ecs.ymlをアップロード
- スタックの詳細を指定 > 各項目に表示されている内容を下記の通り指定。
    - スタック名 > ex.`api-ecs`
    - System Configuration > 全て表示されているデフォルトのまま
    - Netowork Configuration
        - VpcId
            - タグ名 > system-dev-vpc
        - ALBAllowInboundIP
            - [こちらから](https://www.cman.jp/network/support/go_access.cgi)自分のネットワークのグローバルIPを取得 
            - xxx.xxx.xxx.xxx/32　※cider範囲は32で固定とすること
        - ALBSubnetId1
            - タグ名 > system-dev-public-subnet-1
        - ALBSubnetId2
            - タグ名 > system-dev-public-subnet-2
        - ECSSubnetId1
            - タグ名 > system-dev-private-subnet-1
        - ECSSubnetId2
            - タグ名 > system-dev-private-subnet-2
    - SSL/TLS Configuration
        - コンソール > AWS Certificate Manager > 証明書 > 上記で作成した証明書を選択
        - ARNをコピーする
        - Cloudformationに戻りコピーしたARNを転記
    - Fargate Configuration
        - ECSImage
            - コンソール > Amazon ECR > リポジトリ > api-dev-repo > イメージの URI > URI のコピー
            - フロントとAPIのリポジトリを間違えないように
        - Cloudformationに戻りコピーしたURLを転記
    - 上記以外の設定は全てデフォルト表示のままでOK
- スタックオプションの設定 > 次へ > 
    - 　> AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。 > チェック> 送信

### タスク定義書（taskdef.json）の更新

本記事では省略するため、ECS構築時に吐き出されるタスク定義書をそのまま活用します。

ただし、`"image":`タグの箇所はプレースホルダーに書き換えることを注意してください。

- マネージメントコンソール > Amazon Elastic Container Service > api-dev-cluster > タスク
- リビジョンを一つ選択 > json > クリップボードにコピー
- `go-graphql-jwt-server`配下の`taskdef.json`にそのまま貼り付ける
- `"image":`タグの箇所を以下を参考に`"image": "<IMAGE1_NAME>",`へ修正する

![スクリーンショット 2023-05-13 12.37.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/c7829fb7-6be9-4e30-de51-7245f334a082.png)

![スクリーンショット 2023-05-13 12.44.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/96eeb086-9cf0-3304-686a-40ca59659a41.png)

```diff_json
{
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:xxxxxxx:task-definition/api-dev-task-definition:1",
  "containerDefinitions": [
    {
      "name": "api-container",
-      "image": "xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/api-dev-repo:latest",
+      "image": "<IMAGE1_NAME>",
      "cpu": 0,
      "memoryReservation": 128,
      "links": [],
      "portMappings": [
```

### フロント用のECS構築

- 同様の手順でフロントアプリケーション用のECSも構築
- 設定ファイルは/front/ecs.yml
- taskdef.jsonも同様に更新

## cicd.yml（API ・フロント計２種構築）

### System ManagerのパラメーターストアにCodeBuild用の環境変数の登録

IPガチャと呼ばれるToo Many Requests.対策のためDocer Hubのパーソナルアクセストークンを利用しています。

https://dev.classmethod.jp/articles/codebuild-has-to-use-dockerhub-login-to-avoid-ip-gacha/

https://www.creationline.com/lab/29979

DockerHubにログイン後に以下の画像を参考にユーザーIDとアクセストークを取得してください。

![スクリーンショット 2023-05-07 15.59.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/dea50788-0873-8fae-ee13-42dee477f051.png)

|転記元  |SSMでのキー|
|---|---|
|ユーザーID  |DOCKER_HUB_PERSONAL_ACCOUNT_USER_ID  |
|作成したトークン  |DOCKER_HUB_PERSONAL_ACCOUNT_USER_TOKEN  |

ここまでで最終的に、System Managerへ以下のような形で環境変数が格納されていれば問題ありません。

![スクリーンショット 2023-05-07 16.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/82d78a3b-eed2-3ae2-4658-7215739a76ce.png)

### スタックアップロード

- 上記と同様な手順で/common/cicd.ymlをアップロード
- Netowork Configuration
    - VpcId
        - system-dev-vpc
    - CodeBuildSubnetId1
        - system-dev-private-subnet-1
    - CodeBuildSubnetId2
        - system-dev-private-subnet-2
- System Configuration
    - Environment
        - デフォルト表示のままでOK
- ECR/ECS Configuration
    - ECRName
        - デフォルト表示のままでOK
- GitHub Configuration
    - GitHubOrganizationName
    - GitHubRepositoryName
        - ex. https://github.com/OrganizationName/RepositoryName
    - GitHubBranchName
        - フロントとAPIをリポジトリからそのままクローン、`main`ブランチの場合はデフォルト表示のまま

### Code Star Connectionを使ったGitHub連携

CodeStar Connectionsを用いてCodePipeLine内においてsourceステージはGithubで利用します。

- AWSコンソール > CodePipeLine > 設定 > 接続 > 保留中の接続を更新 > github側で承認(画像を参照)
- フロントも同様に設定

![スクリーンショット 2023-05-08 6.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/20345698-d081-3035-225e-a5c997b8a634.png)

![apl-dev-cicd-github.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/7ac2be15-1c5f-99d3-3337-e1b68a4a8bef.png)

![AWS Connector for GitHub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/cfd2e2dc-6338-c5d0-6a5d-53af9ecff0b9.png)

### Code Deploy Group登録

※CodeDeployのみ用いたBlue/Greenデプロイはデプロイグループの登録については、Cloudformationが対応していません。CloudFormation を使用して、CodeDeploy を介して ECS ブルー/グリーンデプロイを実行する方法(hooks利用)もあるのですが、ここでは手動で対応します。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/blue-green.html

**デプロイグループ名を取得する**
- AWSコンソール > cloudformation > cicdスタックを選択 > 出力 > キー”CodeDeployGroupName” > 値をコピー
- 上記の手順でAPIとフロントアプリケーション両方をコピーする

**デプロイグループを登録**
- AWSコンソール > CodeDeploy > アプリケーション > アプリケーション名を選択 > デプロイグループの作成 > デプロイグループ名 > 上記でコピーした内容を転記
    - api-dev-deployment-group
- サービスロール
    - api-dev-cicd-deploy-role
- 環境設定
    - api-dev-cluster
    - api-dev-service
- Load balancer
    - Load balancer選択
        - api-dev-alb
    - 本稼働リスナーポート
        - HTTPS:443
    - テストリスナーポート - オプショナル
        - HTTP:8080
    - ターゲットグループ 1 の名前
        - api-dev-tg-blue
    - ターゲットグループ 2の名前
        - api-dev-tg-green
- デプロイ設定
![デプロイ設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/2f0301ed-8ec3-34da-93e1-38825b15741a.png)

### フロント用のCodePipeLine構築

- 同様の手順でフロントアプリケーション用のCICDも構築。
- 設定ファイルは/front/cicd.yml
- Code Star Connection/Code Deploy Groupも忘れず対応すること。

## rds.yml（共通）

- 上記と同様な手順で/common/rds.ymlをアップロード
- System Configuration
    - Environment
        - デフォルト表示のままでOK
- EC2 Configuration
    - EC2PublicSubnet
        - system-dev-public-subnet-1
    - EC2ImageId
        - デフォルト表示のままでOK
    - KeyName
        - 上記で作成したキーペアを利用
- RDS Configuration
    - 以下二つは後でSystem Managerに登録する必要があるので必ず控えておくこと。
    - DBMasterUsername
        - user
    - DBMasterPassword
        - 任意のパスワードを入力。デフォルトでは”password”。
    - DBPrivateSubnet1
        - system-dev-private-subnet-3
    - DBPrivateSubnet2
        - system-dev-private-subnet-4
- Common Security group Configuration
    - VpcId
        - system-dev-vpc
    - SourceIpAddress
        - 以下のURLから自分のネットワークのグローバルIPを取得 
        - xxx.xxx.xxx.xxx/32　※cider範囲は32で固定とすること
        - https://www.cman.jp/network/support/go_access.cgi
    - TaskSecurityGroup
        - api-dev-task-sg
    - CodeBuildSecurityGroup
        - api-dev-codebuild-sg

### Systems Managerへ環境変数登録

上記で作成したレコード（ドメイン）をSystems Managerに登録します。

|SSMでのキー  |値 |
|---|---|
|API_DB_HOST |コンソール画面 > RDS > エンドポイント  |
|API_DB_USER |上記で作成したユーザー名 |
|API_DB_PASS |上記で作成したパスワード  |

### 踏み台EC2経由でアクセスしてRDSにDBを作成する

- コンソール　> EC2 > rds-dev-ec2-bastion > パブリック IPv4 アドレス >　コピー

- ローカルマシンで以下を実行

```sh
// 踏み台EC2にログイン
$ ssh -i ~/.ssh/db-access-key.pem ec2-user@${上記で取得した"EC2"のパブリックIPを入力}

// RDSにログイン
$ mysql -h ${"API_DB_HOST"を入力} -u user -p

// パスワード
password

// DB作成
CREATE DATABASE golang;

// 内容確認
show databases;
```

## Route53でレコード登録（API ・フロント計２種構築）

- Route53 > ホストゾーン > exapmle.com > レコードを作成
- 以下の画像を参考にAPIとフロント用にサブドメインを作成
    - front.example.com
    - api.example.com
- 上記で作成したALBとレコードを紐づける

![スクリーンショット 2023-05-10 5.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/8eb13c64-001b-4490-75dc-8e22a5861e8b.png)
￼
![修正_68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f313832343734302f39353837643030372d623263302d383964622d343536342d6132313361343931626264622e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/da180662-8d74-6ff1-3258-94c72ecb092a.png)

### Systems Managerへ環境変数登録

上記で作成したレコード（ドメイン）をSystems Managerに登録します。

|SSMでのキー  |値 |
|---|---|
|API_APP_DOMAIN  |example.com  |
|API_FRONT_URL  |https://front.example.com  |
|NEXT_PUBLIC_API_URL  |https://api.example.com  |

# Blue/Greenデプロイ動作確認

上記で作成したインフラリソースをもとにGoで作成されたAPIでBlue/Greenデプロイが行われていることを確認していきます。

以下、手順で動作確認を行なっていきます。

(1) `go-graphql-jwt-api`のヘルスチェック用のルート`/healtcheck`のレスポンスを修正

```diff_go

// pkg/adapter/http/route/route.go

	e.GET("/healthcheck", func(c echo.Context) error {
- 		return c.String(http.StatusOK, "OK")
	})
 	e.GET("/healthcheck", func(c echo.Context) error {
+		return c.String(http.StatusOK, "New deployment test")
	})

```

(2) `main`ブランチにプッシュ

```sh

$ git commit -m "deploy: try B/G deploy"
$ git push origin main

```

(3) CodePipelineの管理画面で実行結果を確認

![スクリーンショット 2023-05-13 15.44.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/f447f7ca-796e-c491-9c24-38525d056834.png)

(4) デプロイ許可を行う

![スクリーンショット 2023-05-13 15.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/049f67bc-a6e1-9b5e-427e-dac4c74a47dd.png)

(5) ブラウザからテストポート（8080）でアクセスして変更が反映されていることを確認

ブラウザで`http://api.webengrchild.com:8080/healthcheck`にアクセス
![スクリーンショット 2023-05-13 15.51.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/aabd4b35-8f3e-4a81-50c2-8b556d7f9a51.png)

(7) 管理画面からトラフィックを本番ポート（443）に切り替える

![03CE2BDA-0FBC-4438-ABAB-FF295F854CE7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/e3d03c6a-ee46-f429-c65f-bc66872b624c.jpeg)


(6) ブラウザから本番ポート（443）でアクセスして変更が反映されていることを確認

![スクリーンショット 2023-05-13 13.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/aed5ccfd-826b-3069-8b0d-4801f7baeef4.png)

(7)トラブルが発生した場合を想定して、ロールバックすることで即座に古いリビジョンに戻す

 ![スクリーンショット 2023-05-13 13.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/60d5ae21-e1d0-c6e9-b191-80106cbc9598.png)

- ブラウザで`https://api.webengrchild.com/healthcheck`に再度アクセスして元のリビジョンに切り替わっていることを確認する

![スクリーンショット 2023-05-13 14.30.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/05a421d7-e29a-d5bc-a180-13feccb840f1.png)


# アプリケーションの最終確認

- `go-graphql-server`と`next-front-app`がそれぞれデプロイされていることを確認

 ![スクリーンショット 2023-05-13 14.13.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/61ee812a-2818-9a26-5feb-11e8fbdebd27.png)

![スクリーンショット 2023-05-13 14.41.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1824740/3176fc3d-c5a8-030e-26bb-afca97fa871f.png)

# おわりに

ここまで長々とお付き合い頂きありがとうございました。

私自身も、久しぶりにフルスタックなアプリケーションを作成したため非常に学びの多い機会でした。

拙い部分多々あったかと思いますが、少しでもお役に立てれば幸いです。

:::note info
■ご案内■

- [【環境構築編】](https://qiita.com/WebEngrChild/items/d4bc23bf352e7aa46361)　
- [【Next.js編】](https://qiita.com/WebEngrChild/items/6e9e3232046301879089)
- [【Go編】](https://qiita.com/WebEngrChild/items/d9b87944235c5220ae5b)
- [【AWS編】](https://qiita.com/WebEngrChild/items/ca93783f8ae6bee7f985)

これからも頑張ってハンズオン系の記事を書いていきたいと思っているので、いいねっと思って頂けたら**LGTM**押していただけると励みになります！

:::