【AWS】EC2にログインしてからの環境構築（SpringBoot + MySQL）

どうも、puchankoです。
AWSの学習をしようと思い、まずは基本的な構成でVPC内にEC2とRDSを置いて、自分で作ったSpringBootアプリケーションを動かしてみようとすると、なかなか上手くいかず、予想外のところでつまずいたポイントが色々あったので備忘録として残す。

# 記事の構成
| 項番 | ページ内リンク |
|:----:|:-------------|
| 0 | [はじめに](#0-はじめに) |
| 1 | [最初の設定](#1-最初の設定) |
| 2 | [メモリ領域の割り当て](#2-メモリ領域の割り当て) |
| 3 | [Javaのインストール](#3-Javaのインストール) |
| 4 | [Apacheのインストール](#4-Apacheのインストール) |
| 5 | [Tomcatのインストール](#5-Tomcatのインストール) |
| 6 | [MySQLのインストール](#6-MySQLのインストール) |
| 7 | [Javaプログラムを実行する](#7-Javaプログラムを実行する) |
| 8 | [参考記事](#8-参考記事) |



# 0-はじめに

### 記事の内容
本記事ではAWSのEC2内にログインした後の環境構築に関する部分のみにフォーカスを当てたため、90%以上Linuxコマンドしか出てきません。
そのため、アプリケーションの作成方法、AWSコンソール上での設定方法などについては一切触れておりませんのでご理解ください。

### 前提条件
- AWSのVPC内のパブリックサブネットにEC2、プライベートサブネットにRDSを配置
- EC2はSSH、HTTPからのアクセスが可能
- RDSはEC2からのみアクセス可能
- SpringBoot 3でアプリケーションを作成済みと仮定
- アプリケーションにアクセスするためのポート番号は8085に設定
- EC2のAMI：Amazon Linux 2
- RDSのエンジンとそのバージョン：MySQL 8.0.3

### おことわり
私はまだまだキャリアの浅い新米エンジニアのため、もしかしたら記事の内容に誤りがあったり、解釈が誤っている箇所があるかもしれません。その場合は是非ともご指摘いただけると幸いです。

### 表記、表現
- ローカルのターミナルで作業をしている場合はファイル名の部分を「local」としています。
```shell:local
# ↑このように「local」としています。
```
- EC2にログインしてから作業をしている場合はファイル名の部分を「ec2-user」としています。
```shell:ec2-user
# ↑このように「ec2-user」としています。
```

- 別途、ファイルの書き込み操作などをしている場合は以下のようになります。
```shell:/hoge/fuga
# ↑hogeディレクトリにあるfugaファイルに書き込む。
```
では本題に進みます。


# 1-最初の設定
- キーペアに権限(読み書き)を付与する（初回のみ）
```shell:local
chmod 600 /Users/puchanko/my-keypair.pem
```
- EC2にログインする
```shell:local
ssh -i /Users/puchanko/my-keypair.pem ec2-user@12.34.567.890

# 初回のみ確認されるため「yes」と入力してEnterキー押下でログイン可能
```

- EC2に無事にログインができたら、一旦EC2から抜ける
```shell:ec2-user
exit
```

- 作成したアプリケーションのjarファイルをEC2のホームディレクトリにコピーする
```shell:local
scp -i /Users/puchanko/my-keypair.pem sample-app-0.0.1-SNAPSHOT.jar ec2-user@12.34.567.890:/home/ec2-user/
```

- 再びEC2にログインする
```shell:local
ssh -i /Users/puchanko/my-keypair.pem ec2-user@12.34.567.890
```

- EC2のホームディレクトリに先ほどコピーしたjarファイルが存在するか確認する
```shell:local
ls

# 実行結果
# sample-app-0.0.1-SNAPSHOT.jar
```


- パッケージを最新の状態にするために更新をする
```shell:ec2-user
sudo yum update -y
```

# 2-メモリ領域の割り当て
学習用としてEC2を利用する場合、おそらく無料利用枠内で利用すると思うのだが、その場合でさまざまなソフトウェアのインストールを行うとマシンのメモリ領域がすぐに不足する為、あらかじめスワップ領域として動作するためのメモリ領域の割り当てを行う。
- [スワップファイルを使用して、Amazon EC2 インスタンスのスワップ領域として機能するようにメモリを割り当てるにはどうすればよいですか?](https://repost.aws/ja/knowledge-center/ec2-memory-swap-file)
- [AWS EC2 インスタンスに swap 領域を作成する](https://zenn.dev/wsuzume/articles/3ef4b2d3caf203)
- [EC2にSwapメモリを作成](https://engineer-blog.ajike.co.jp/ec2-swap/)
- [スワップ領域（swap領域）](https://wa3.i-3-i.info/word1721.html)
<br>

- 現在のメモリ使用状況を確認する
```shell:ec2-user
free -m

# 実行結果
<< COMMENT_OUT
              total        used        free      shared  buff/cache   available
Mem:            952          76         274           0         601         737
Swap:             0           0           0
COMMENT_OUT
# Swap のところが0になっている = スワップ領域にメモリが割り当てられていないということ
```

- スワップ領域としてメモリを割り当てる
```shell:ec2-user
# ddコマンドで実体を伴う /swapfile を作成する。(この例では4GB(128MBx32)のメモリ領域を割り当てる)
sudo dd if=/dev/zero of=/swapfile bs=128M count=32

# 実行結果
<< COMMENT_OUT
32+0 レコード入力
32+0 レコード出力
4294967296 バイト (4.3 GB) コピーされました、 64.5807 秒、 66.5 MB/秒
COMMENT_OUT
```

- スワップファイルに権限(読み書き)を設定する
```shell:ec2-user
sudo chmod 600 /swapfile
```

- スワップ領域のセットアップをする
```shell:ec2-user
sudo mkswap /swapfile

# 実行結果
<< COMMENT_OUT
スワップ空間バージョン 1 を設定します。サイズ = 4 GiB (4294963200 バイト)
ラベルはありません, UUID=00x000x0-xx0x-0xx0-00xx-x000xx0000xx
COMMENT_OUT
```

- スワップ領域にスワップファイルを追加して、スワップファイルを即座に使用できるようにする
```shell:ec2-user
sudo swapon /swapfile
```

- スワップ領域の割り当てが正常に完了したことを確認する
```shell:ec2-user
sudo swapon -s
# 実行結果
<< COMMENT_OUT
ファイル名				タイプ		サイズ	使用済み	優先順位
/swapfile                              	file    	4194300	0	-2
COMMENT_OUT
```

- `/etc/fstab` ファイルを編集する
```shell:ec2-user
sudo vi /etc/fstab
```

- EC2が再起動時にもスワップファイルが起動するように設定する
```vim:/etc/fstab
UUID=00x000x0-xx0x-0xx0-00xx-x000xx0000xx     /           xfs    defaults,noatime  1   1
/swapfile swap swap defaults 0 0
```
:::note warn
- ここで記述するUUIDは`sudo mkswap /swapfile`のときに発行されたUUIDに書き換える。
- `/swapfile swap swap defaults 0 0`を追記する。
:::

- 改めて現在のメモリ状況を確認する
```shell:ec2-user
free -m

# 実行結果
<< COMMENT_OUT
              total        used        free      shared  buff/cache   available
Mem:            952          68         182           0         701         745
Swap:          4095           0        4095
COMMENT_OUT
```
::: note info
`Swap`の`total`が`4095`(=4GB)になっていれば、メモリの割り当てが無事にできているということなのでOK。
:::

# 3-Javaのインストール
- OpenJDK(Java17)をインストールする
https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-17-ug/amazon-linux-install.html
```shell:ec2-user
sudo yum install java-17-amazon-corretto-devel
```

- Javaのバージョンを確認する
```shell:ec2-user
java -version

# 実行結果
<< COMMENT_OUT
openjdk version "17.0.9" 2023-10-17 LTS
OpenJDK Runtime Environment Corretto-17.0.9.8.1 (build 17.0.9+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.9.8.1 (build 17.0.9+8-LTS, mixed mode, sharing)
COMMENT_OUT
```
::: note warn
PATHを通す(JAVA_HOME)設定は後述の`tomcat.service`にて実施をする。
:::

# 4-Apacheのインストール
- Apacheをインストールする
```shell:ec2-user
sudo yum install httpd -y
```

- Apacheを起動する
```shell:ec2-user
sudo systemctl start httpd
```

- Apacheが起動しているかどうか確認する
```shell:ec2-user
sudo systemctl status httpd.service
# active と表示されたらOK
```

- システムの起動と同時にApacheも自動起動するように設定する
```shell:ec2-user
sudo systemctl enable httpd
```

- Apacheの自動起動が有効かどうかを確認する
```shell:ec2-user
sudo systemctl is-enabled httpd
# enabled と表示されたらOK
```

# 5-Tomcatのインストール
- Tomcat の実行ユーザー (システムアカウント) を作成する
```shell:ec2-user
sudo useradd -r -s /sbin/nologin tomcat
```

- アカウントの確認
```shell:ec2-user
id tomcat

# 実行結果
# uid=995(tomcat) gid=993(tomcat) groups=993(tomcat)
```

- Tomcat10パッケージをダウンロードする
:::note warn
Tomcatのパッケージのバージョンは公式サイトで事前に確認すること。
https://dlcdn.apache.org/
:::
```shell:ec2-user
wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.16/bin/apache-tomcat-10.1.16.tar.gz
```

- ダウンロードしたパッケージを解凍する
```shell:ec2-user
tar -zxvf apache-tomcat-10.1.16.tar.gz
```

- 解凍したファイルを実行ディレクトリへ移動させる
```shell:ec2-user
sudo mv apache-tomcat-10.1.16 /usr/local/src/
```

- tomcatコマンドで起動させるため、シンボリックリンクを作成する
```shell:ec2-user
sudo ln -s /usr/local/src/apache-tomcat-10.1.16 /usr/local/src/tomcat
```

- 所有権を付与する
```shell:ec2-user
sudo chown -R tomcat:tomcat /usr/local/src/apache-tomcat-10.1.16

sudo chown -R tomcat:tomcat /usr/local/src/tomcat
```

- ユニットファイル (tomcat.service) を作成する
```shell:ec2-user
sudo vi /etc/systemd/system/tomcat.service
```

- `tomcat.service`に以下の内容を記述する
::: note warn
ここに`JAVA_HOME`の設定も記述するので忘れないようにする。
:::
```vim:/etc/systemd/system/tomcat.service
[Unit]
Description=Tomcat Web Server
After=network.target
 
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64"
Environment="CATALINA_BASE=/usr/local/src/tomcat"
Environment="CATALINA_HOME=/usr/local/src/tomcat"
Environment="CATALINA_PID=/usr/local/src/tomcat/temp/tomcat.pid"
ExecStart=/usr/local/src/tomcat/bin/startup.sh
ExecStop=/usr/local/src/tomcat/bin/shutdown.sh
 
[Install]
WantedBy=multi-user.target
```

- ユニットファイルの再読み込みをする
```shell:ec2-user
sudo systemctl daemon-reload
```

- ユニットファイルの自動起動設定を有効にする
```shell:ec2-user
sudo systemctl enable tomcat.service
```

- ユニットファイルの自動起動設定が有効かどうか確認する
```shell:ec2-user
sudo systemctl is-enabled tomcat.service
# enabled と表示されたらOK
```

- 環境設定のため`.bash_profile`を編集する
```shell:ec2-user
sudo vi ~/.bash_profile
```

- 以下の内容を末尾に追記する(Tomcatの環境変数、DB接続の環境変数の設定)
```vim:.bash_profile
# CATALINA_HOME
export CATALINA_HOME=/usr/local/src/tomcat
 
# SPRING DB CONNECTION
export SPRING_DATASOURCE_URL=jdbc:mysql://<RDSのエンドポイント>:3306/<RDSのDB名>
export SPRING_DATASOURCE_USERNAME=<RDSのユーザー名>
export SPRING_DATASOURCE_PASSWORD=<RDSのパスワード>
export SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
```
:::note warn
SpringBootでアプリケーションを作成した場合、通常はプロジェクト内の`application.yml`または`application.properties`にDB接続情報を記述すると思うが、EC2-RDSでは異なるサブネットでアクセスできないため、EC2の環境変数として設定する必要がある。
https://kumagoro-95.hatenablog.com/entry/2021/02/26/122812
:::

- `.bash_profile`の変更を反映する
```shell:ec2-user
source ~/.bash_profile
```

- Tomcatを起動する
```shell:ec2-user
sudo systemctl start tomcat.service
```

- `tomcat.service`が起動しているか確認する
```shell:ec2-user
systemctl status tomcat.service
# active と表示されたらOK
```

- curlコマンドで動作確認をする
```shell:ec2-user
curl -s http://localhost:8080 | grep title

# 実行結果
<< COMMENT_OUT
       <title>Apache Tomcat/10.1.16</title>
COMMENT_OUT
# 上記のように表示されたらOK
```

# 6-MySQLのインストール
- 先にMariaDBのパッケージを削除しておく
```shell:ec2-user
sudo yum remove mariadb-libs
```

- MySQLのリポジトリをインストールする
```shell:ec2-user
sudo yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
```

- 設定を有効化する
```shell:ec2-user
sudo yum-config-manager –enable mysql80-community
```

- MySQL8.Xのリポジトリが、`enabled=1`になっているかを確認する
```shell:ec2-user
sudo cat /etc/yum.repos.d/mysql-community.repo

# 実行結果
<< COMMENT_OUT
# Enable to use MySQL 8.0
[mysql80-community]
name=MySQL 8.0 Community Server
baseurl=http://repo.mysql.com/yum/mysql-8.0-community/el/6/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
COMMENT_OUT

# enabled=1 となっている = 有効なのでOK
```

- MySQLをインストールするために、GPGKeyをインポートしておく
```shell:ec2-user
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
```
:::note info
参考
- [GPGキーの関係でmysqlがインストールできない時の対処法](https://qiita.com/yuyanstart/items/e8a6f1d2fd7cbf1cfd59)
- [GPGキー とは](https://qiita.com/miyuki_samitani/items/9c155111220cecac5154)
:::

- MySQLをインストールする
```shell:ec2-user
sudo yum install mysql-community-server
```

- MySQLのバージョンを確認する
```shell:ec2-user
mysqld --version

# 実行結果
# /usr/sbin/mysqld  Ver 8.0.35 for Linux on x86_64 (MySQL Community Server - GPL)
```

- MySQLの起動する
```shell:ec2-user
sudo systemctl start mysqld.service
```

- MySQLの起動状態の確認
```shell:ec2-user
sudo systemctl status mysqld.service
# active と表示されたらOK
```

- MySQLの自動起動設定を有効化する
```shell:ec2-user
sudo systemctl enable mysqld.service
```

- MySQLの自動起動設定が有効かどうか確認する
```shell:ec2-user
sudo systemctl is-enabled mysqld.service
# enabled と表示されたらOK
```

- MySQLにログインをする
```shell:ec2-user
mysql -h <RDSのエンドポイント> -P 3306 -u <RDSのユーザー名> -p

# password を聞かれるので、<RDSのパスワード>を入力する
```
:::note warn
DBの確認や、必要となるユーザー作成、スキーマ作成、テーブル作成、データ投入などの作業をこのタイミングで実施する。
:::

- MySQLから抜ける
```sql:mysql
exit
```

# 7-Javaプログラムを実行する
```shell:ec2-user
java -jar sample-app-0.0.1-SNAPSHOT.jar
```

- ブラウザからアクセスしてみる
http://12.34.567.890:8085/
(上記URLは本記事用の架空のURLのため、アクセスできません。)
作ったアプリケーションが表示されたらOK！！

# 8-参考記事
- [スワップファイルを使用して、Amazon EC2 インスタンスのスワップ領域として機能するようにメモリを割り当てるにはどうすればよいですか?](https://repost.aws/ja/knowledge-center/ec2-memory-swap-file)
- [AWS EC2 インスタンスに swap 領域を作成する](https://zenn.dev/wsuzume/articles/3ef4b2d3caf203)
- [EC2にSwapメモリを作成](https://engineer-blog.ajike.co.jp/ec2-swap/)
- [Amazon Corretto 17 Installation Instructions for Amazon Linux 2 and Amazon Linux 2023](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-17-ug/amazon-linux-install.html)
- [AWS(EC2,RDS(MySQL))環境にSpringBootで作成したアプリをデプロイ](https://kumagoro-95.hatenablog.com/entry/2021/02/26/122812)
- [GPGキーの関係でmysqlがインストールできない時の対処法](https://qiita.com/yuyanstart/items/e8a6f1d2fd7cbf1cfd59)
- [GPGキー とは](https://qiita.com/miyuki_samitani/items/9c155111220cecac5154)
- [EC2にMySQL8.Xをセットアップする](https://qiita.com/Hide-Zaemon/items/caa7ff79b3322b6af14a)