Spring BootアプリをAWSにデプロイする【前編】

## はじめに
Spring Bootで作成したCRUDアプリケーションをAWSにデプロイし、更にさくらレンタルサーバーで追加したサブドメインからHTTPSアクセスできるようにする手順についてまとめます。

前編では、AWS環境を構築していきます。
- VPCの構築
- Webサーバーの構築
- DBサーバーの構築

後編では、くらレンタルサーバーで追加したサブドメインからHTTPSアクセスできるようにする手順についてまとめています。

https://qiita.com/ioaio/items/54b6eb9f6551342ac658

## 前提（この記事では触れない内容）
- AWSのアカウント登録
- さくらのドメイン取得
- Spring Bootアプリケーションの作成

## 構成図
今回構築する環境のイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/be58041b-63b7-ab98-975c-d69bd6d2f94c.png)

## VPCの構築
AWSでは **VPC（Virtual Private Cloud）** と呼ばれる領域を作成することで、好きな構成のネットワークを構築できます。

:::note
VPCとは、ユーザーがAWSクラウド内に専用の仮想ネットワークを構築できる機能です。このネットワークは、他のAWSユーザーから論理的に分離されており、ユーザーは自分のリソースを安全に管理し、運用することができます。
:::

ここでは、以下の4つを作成します。
- VPC
- サブネット
- インターネットゲートウェイ
- ルートテーブル

### 1. VPCを作成する
`マネジメントコンソール → VPC → お使いのVPC → VPCを作成` からVPCを作成します。

今回は「10.0.0.0/16」という CIDRブロックをもった「VPC領域」という名前のVPCを作成します。

![ap-northeast-1.console.aws.amazon.com_vpcconsole_home_region=ap-northeast-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/23ca9833-c2bf-a6f5-27b5-7d0f4cab0675.png)

### 2. VPCをサブネットに分割する
上記のように、**VPC** を作成する時には **「どのようなIPアドレスの範囲を使うか」** を指定します。このようなネットワークにおけるIPアドレスの範囲を定義するための方法を、**CIDRブロックの割り当て** と言います。

また、作成したVPCはいくつかのネットワークに更に分割して利用します。この分割したネットワークの事を **サブネット** と呼びます。

今回は、次の2つのサブネットに分割します。

**① パブリックサブネット（10.0.1.0/24）**
- インターネットに接続することを目的としたサブネット
- ここにWebサーバーを設置して、インターネットからアクセスできるようにします

**② プライベートサブネット（10.0.2.0/24）**
- インターネットから隔離したサブネット
- インターネットから直接アクセスできないので、セキュリティを高めらます
- ここにデーターベースサーバーを設置します

:::note
サブネットのCIDRブロックは、VPCのCIDRブロック内に収める必要があり、他のサブネットと重複してはいけません。
:::

`VPCダッシュボード → サブネット → サブネットを作成` からサブネットを作成します。

[VPC ID] の部分に先ほど作成したVPCを選択し、[IPv4 サブネット CIDR ブロック] に「10.0.1.0/24」を設定し、「パブリックサブネット」という名前でサブネットを作成します。

![ap-northeast-1.console.aws.amazon.com_vpcconsole_home_region=ap-northeast-1 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/893b7ff4-c9d2-1342-072f-0ee555795b2d.png)

### 3. インターネットゲートウェイの作成
上記で作成したパブリックサブネット（10.0.1.0/24）をインターネットに接続します。AWSでサブネットをインターネットに接続するには、**インターネットゲートウェイ** を利用します。

インターネットゲートウェイを使用するためには、以下の手順が必要です：
- **インターネットゲートウェイの作成**：AWS管理コンソールからインターネットゲートウェイを作成
- **VPCへのアタッチ**：作成したインターネットゲートウェイを特定のVPCにアタッチ
- **ルートテーブルの設定**：インターネットゲートウェイを使用するサブネットのルートテーブルに、インターネットゲートウェイへのルートを追加

上から順に一つずつ確認していきます。

#### 3-1. インターネットゲートウェイの作成

`VPCダッシュボード → インターネットゲートウェイ → インターネットゲートウェイの作成` からインターネットゲートウェイを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/1b45e647-f84a-dc74-fb4c-5722fa0f3a2a.png)

#### 3-2. VPCへのアタッチ
作成したインターネットゲートウェイを選択して [アクション] から [VPCにアタッチ] を選択し、上記で作成したVPCにインターネットゲートウェイを結び付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/08e4e03d-dd72-b7b8-1f41-9bc8f7738f1a.png)

#### 3-3. ルートテーブルの設定
ネットワークにデータを流すためには、**ルーティング情報** と呼ばれる設定が必要です。この設定をAWSでは、**ルートテーブル** と呼びます。

インターネットゲートウェイを使用するサブネット（今回の場合「パブリックサブネット」）のルートテーブルに、インターネットゲートウェイへのルートを追加します。これにより、そのサブネット内のリソースがインターネットへアクセスできるようになります。

:::note
ルートテーブルは、VPC内でどのトラフィックがどの方向に向かうかを示す「ルール」の集合であり、ネットワーク内のデータの流れを管理します。

各サブネットは、特定のルートテーブルに関連付けられます。これにより、そのサブネット内のインスタンスがどのように外部と通信するかが決まります。
:::

`VPCダッシュボード → ルートテーブル → ルートテーブルの作成` からルートテーブルを作成します。

上記で作成したVPCを選択し、「パブリックテーブル」という名前でルートテーブルを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/b34d1314-c85f-49b8-b197-e386686d2118.png)

`作成したルートテーブルを選択 → サブネットの関連づけタブ → サブネットの関連づけを編集`　からパブリックサブネットとの関連づけを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/35449875-ef2c-1299-1913-b8a57ee44640.png)

割り当てたいサブネット（今回の場合「パブリックサブネット」）にチェックを入れ、[関連付けを保存] を押下します。これで、パブリックサブネットに対して、新たに作成したルートテーブル（パブリックテーブル）が連携されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/735524f4-0bf1-9e0b-02ce-8d0f2e711179.png)

`作成したルートテーブルを選択 → ルートタブ` からルーティング情報を確認します。

![ap-northeast-1.amazonaws.com_0_3917178_3b7e7374-6d7b-ebbd-cb52-3de100e57dfe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/69ad1d92-bd85-7bb9-b2b6-eebd2743b77a.png)


デフォルトのルートテーブルは、**送信先：1.0.0.0/16、ターゲット：local** の1項目だけが設定されています。これは、「1.0.0.0/16」に含まれるIPアドレス宛てのパケットであれば、自身のルーター（ローカル）にパケットを転送するという意味です。

つまり、現在のルートテーブルの設定では **「10.0.0.0/16以外の宛先のパケット」は全て破棄されます。** インターネット通信ができるように、[ルートを編集] からルーティング情報を編集します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/09b6f567-8321-2466-78f4-87fcddc4b337.png)

送信先に「0.0.0.0/0」を、ターゲットに「作成したインターネットゲートウェイ」を追加します。このように、**「10.0.0.0/16以外の宛先のパケット」をインターネットゲートウェイに転送するようルートテーブルを変更**することで、インターネットと通信できるようになります。

`VPCダッシュボード → サブネット → パブリックサブネットを選択 → ルートテーブルタブ` から正しいルートテーブルが設定されているかを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/0164e934-a35d-9789-b6ee-0b4eeb975f09.png)

これで、パブリックサブネットがインターネットへ接続できるようになりました。

## Webサーバーの構築
次に、パブリックサブネットの中に仮想サーバーを構築していきます。仮想サーバーは **Amazon EC2** を用いて作成します。EC2で作成した仮想サーバーのことをAWSでは、**インスタンス** と呼びます。

このインスタンスにApache（Webサーバーソフト）をインストールすることで、Webサーバーとして機能させます。

ここでは以下の3つの作業を行います。
- EC2インスタンスの作成（WEBサーバー）
- Apacheのインストール
- ファイアウォールの設定
- DNSサーバーの構築

### 1. EC2インスタンスの作成（Webサーバー）

`マネジメントコンソール → EC2 → インスタンスを起動` から作成したVPCのパブリックサブネットの中にEC2インスタンスを設置します。

今回は以下の通り設定しました。

- **AMI**：Amazon Linux
- **インスタンスタイプ**：t2.micro
- **キーペア**：任意の名前を入力、その他はデフォルト値で新しいキーペアを作成
- **ネットワーク設定**：作成したVPC及びパブリックサブネットを設定、[パブリックIPの自動割り当て] は「有効化」を選択
- **セキュリティーグループ**：任意の名前を入力、その他はデフォルト値のまま作成
- **セキュリティグループルール**：SSHの項目があることを確認
- **高度なネットワーク設定**：[プライマリIP] に「10.0.1.10」と入力
- **ストレージ設定**：デフォルト値のまま

設定が完了したら [インタンスを起動] を押下します。
しばらくして [インスタンスの状態] が「実行中」になったらインスタンスの作成完了です。

### 2. Apacheのインストール

作成したインスタンスへ、ダウンロードしたキーペアファイル（SSH認証鍵）を使ってSSHログインします。

:::note info
インスタンスのパブリックIPアドレスは、EC2ダッシュボード → インスタンス → 作成したインスタンスを選択 → 詳細タブの **[パブリック IPv4 アドレス]** 欄 から確認できます。
:::

:::note info
Amazon Linux では **「ec2-user」** というデフォルトのユーザーがあらかじめ設定されているので、このユーザーでログインします。
:::

ログインが出来たら、次のコマンドを入力して **Apache HTTP Server** をインストールします。
```linux
$ sudo dnf -y install httpd
```

インストールが完了したら、Apacheを起動します。
```linux
$ sudo systemctl start httpd.service
```

サーバーが起動する時に、Apacheも自動起動するように構成します。
```linux
$ sudo systemctl enable httpd.service
```

これで、Webサーバーが構築できました。試しにWebブラウザで ``http://パブリックIPアドレス/`` に接続してみます。今の状態だと、ポート80番がファイアウォールによってブロックされている為、接続できないはずです。

### 3. ファイアウォールの設定

Amazon EC2でファイアウォール機能を構成するのは、**セキュリティグループ** という機能です。

:::note
**セキュリティグループ** はVPC内で動作する **仮想ファイアウォール** の一種です。主に、EC2インスタンスなどのAWSリソースに対するネットワークトラフィックを制御するために使用されます。

セキュリティグループは、**インバウンド（受信）** および **アウトバウンド（送信）** トラフィックの許可ルールを設定することで、リソースへのアクセスを管理します。
:::

`EC2ダッシュボード → セキュリティグループ → インスタンス作成時に作成したセキュリティグループを選択 → インバウンドルールタブ → インバウンドルールを編集` からセキュリティグループの設定画面を開きます。

以下の通り設定し、[ルールを保存] を押下します。

- **タイプ**：カスタムTCP
- **ポート範囲**：80
- **ソース**：Anywhere-IPv4（すべてのホストを示します）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/3adf1448-8e64-a7c1-452a-01de0e3d0ad2.png)

以上の設定で、ポート80番が通るようになりました。
もう一度、``http://パブリックIPアドレス/`` にWebブラウザからアクセスすると、「It works!」というApacheのデフォルトページへアクセスされるようになります。

### 4. DNSサーバーの構築

IPアドレスでなく、ドメイン名を用いてWebサイトにアクセスできるようにインスタンスの名前解決を有効にします。

`VPCダッシュボード → お使いのVPC → 作成したVPCを選択 → アクション →VPCの設定を編集` から、VPCの編集画面を開きます。

![ap-northeast-1.amazonaws.com_0_3917178_52f745a4-0017-c06d-96e5-4da82d173c70.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/8bc007c4-3380-ba3a-bede-97dfc660cfbb.png)


[DNSホスト名を有効化] をチェックし、変更を保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/848e17df-99ff-a773-3c73-b1915a40cb9f.png)

`EC2ダッシュボード → インスタンス → 作成したインスタンスを選択 → 詳細タブ` の **[パブリック IPv4 DNS]** 欄 から割り当てられたDNS名を確認します。
`http://パブリックDNS名/` でWebブラウザからアクセスすると、「It works!」というApacheのデフォルトページへ正しくアクセスできるはずです。

## DBサーバーの構築

ここでは、以下の4つの作業を行います。

- プライベートサブネットの作成
- EC2インスタンスの作成（DBサーバー）
- NATゲートウェイの構築
- MariaDBのインストール

### 1. プライベートサブネットの作成

[VPCをサブネットに分割する](#2.-VPCをサブネットに分割する) を参考に、プライベートサブネットを作成します。プライベートサブネットは、パブリックサブネットと違いインターネットに接続しない為、ルートテーブルはデフォルトのまま変更不要です。

### 2. EC2インスタンスの作成（DBサーバー）

`EC2マネジメントコンソール → EC2 → インスタンスを起動` から作成したVPCのプライベートサブネットの中にEC2インスタンスを設置します。

今回は以下の通り設定しました。

- **AMI**：Amazon Linux
- **インスタンスタイプ**：t2.micro
- **キーペア**：WebサーバーのEC2インスタンス作成時に生成した認証鍵を選択
- **ネットワーク設定**：作成したVPC及びプライベートサブネットを設定、[パブリックIPの自動割り当て] は「無効化」を選択
- **セキュリティーグループ**：任意の名前を入力、その他はデフォルト値のまま作成
- **セキュリティグループルール**：[セキュリティグループのルールを追加] からタイプ「MySQL/Aurora」、ソースは「任意の場所」を選択し、MariaDBの通信ポートである「3306」を通すように設定する
- **高度なネットワーク設定**：[プライマリIP] に「10.0.2.10」と入力
- **ストレージ設定**：デフォルト値のまま

設定の入力が終了したら [インタンスを起動] を押下します。
しばらくして [インスタンスの状態] が「実行中」になったら完了です。

### 3. NATゲートウェイの構築

DBサーバーにはデータベースソフトをインストールし、Webサーバーから利用できるようにしたいです。しかし今回の場合、DBサーバーはプライベートサブネット構築する為、インターネットに接続できません。

そこで今回は、**NATゲートウェイ（Network Address Translation Gateway）** を構築し、プライベートサブネットに存在するホストがインターネット通信できるようにします。

:::note
**NATゲートウェイ**は、VPC内でプライベートサブネットに配置されたインスタンスがインターネットへアクセスできるようにするためのサービスです。

NATゲートウェイを使用することで、プライベートサブネット内のリソースは外部のサービスと通信できますが、外部からの直接的な接続は受け付けません。
:::

`VPCダッシュボード → NATゲートウェイ → NATゲートウェイを作成` からNATゲートウェイの作成を行います。

[サブネット] に「パブリックサブネット」を選択し、[Elastic IP を割り当て] を押下し、Elastic IP を取得します。設定が完了したら、[NATゲートウェイの作成] を押下して、NATゲートウェイを作成します。

![ap-northeast-1.console.aws.amazon.com_vpcconsole_home_region=ap-northeast-1 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917178/bb8cf964-34a6-8ef8-8651-26ed309845f1.png)

次に、プライベートサブネットからインターネット通信するときに、パケットがNATゲートウェイの方向に流れるように、ルートテーブルを更新します。

`VPCダッシュボード → ルートテーブル` から、[メイン] が [はい] になっているメインルートテーブルを選択します。（プライベートサブネットにはこのメインルートテーブルが適用されています）

ここでは、このメインルートテーブルのデフォルトゲートウェイをNATゲートウェイに変更します。[ルート] タブから [ルートを編集] を押下し、[ルートを追加] から「0.0.0.0/0」に対して、NATゲートウェイのIDを選択し、変更を保存します。これでNATゲートウェイの設定が完了しました。

:::note warn
NATゲートウェイは稼働時間と転送バイト単位の両方で課金されるので、使う必要がなくなったら削除しておくのがベターです。
:::

### 4. MariaDBのインストール

DBサーバーにMariaDBをインストールします。DBサーバーはインターネットと接続されていない為、ローカル環境からDBサーバーへ直接SSH接続することはできません。その為、今回は以下のような手順でWebサーバーを踏み台にし、ローカル環境からDBサーバーへアクセスします。

**①WebサーバーにSSH接続**
**②WebサーバーからDBサーバーにSSH接続**

:::note warn
インスタンスにSSH接続するには秘密鍵（キーペア）が必要です。その為、事前に秘密鍵（キーペア）をWebサーバーに置いておく必要があります。
:::

WebサーバーにSSHログイン後、以下のコマンドを実行しDBサーバー（10.0.2.10）にログインします。
```linux
$ ssh -i <秘密鍵ファイル名> ec2-user@10.0.2.10
```

DBサーバーにログインした状態で次のコマンドを入力し、MariaDBをインストールします。
```linux
$ sudo dnf -y install mariadb105-server
```

インストールが完了したら、MariaDBを起動します。
```linux
$ sudo systemctl start mariadb
```

次に、MariaDBを初期化します。質問に従って、MariaDB の rootユーザーのパスワードを設定します。
```linux
$ sudo mysql_secure_installation
```

次に、Spring Bootアプリケーションで利用するデータベースを作成します。mysqlコマンドを実行し、rootユーザーでMariaDBに接続します。
```mysql
$ mysql -u root -p
```

今回は `training` という名前のデータベースを作成します。
```mysql
MariaDB[none]> CREATE DATABASE training DEAFULT CHARACTER SET utf8 COLLATE utf8_general_ci;
```

続いて、ユーザーを作成します。ここでは、`spring` というユーザーを作成し、パスワードは `springpasswd` とします。`spring` ユーザーに作成した `training` データベースに対して、すべてのアクセス権を与えます。

```mysql
MariaDB[none]> grant all on training.* to spring@"%" identified by 'springpasswd';
```

次のコマンドを実行し、上記の権限を反映させます。
```mysql
MariaDB[none]> flush privileages;
```

以上でデータベースの作成は完了です。`exit` と入力し、mysqlから抜けます。最後に、DBサーバーが起動した時にMariaDBを自動的に起動するよう構成しておきます。
```linux
$ sudo systemctl enable mariadb
```

## 最後に
前編では、AWS環境の構築（WebサーバーとDBサーバーの構築と各種設定）まで完了しました。

後編では、今回構築したAWS環境にSpring Bootアプリケーションをデプロイする方法と、さくらのサブドメインからサイトへアクセスできるようにする方法についてまとめます。

https://qiita.com/ioaio/items/54b6eb9f6551342ac658

## 参考書籍
https://www.amazon.co.jp/Amazon-Web-Services%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%86%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89%E6%94%B9%E8%A8%82%EF%BC%94%E7%89%88-%E5%A4%A7%E6%BE%A4-%E6%96%87%E5%AD%9D/dp/4296202049