技術系

Java × React × Dockerで簡易アプリ作るよ②

技術系

こんにちは、なかにしです。

前回のおまけとして、前回作成したjarファイルをAWS上で動かしてみようと思います。

前提

OS:Windows
使用ツール:Tera Term

手元にSpring bootとReactで作成し、jar化されたアプリケーションがあること。

AWS側の設定

AWSにログインし、各種設定を行います。

セキュリティグループの設定

セキュリティグループとは、「何を許可し、何を許可しないのか」のルールをまとめたグループです。

EC2はデフォルトですべてのアクセスを拒否するので、
「このアクセスは通していいよ」というのを「インバウンドルール」に設定します。

例として、EC2にspring bootを入れ、ポート8080で動かしたとします。
このとき、ローカルだとlocalhost:8080でアクセスができますが、EC2はアクセス許可をしていないので、拒否されます。

これを回避する為に「インバウンドルール」に8080を設定し、
誰でもアクセスできるようにする、といった使い方をします。

EC2 > セキュリティグループを選択します。

セキュリティグループの作成を押下します。

各種設定の入力をしていきます。

セキュリティグループ名:好きな名前
インバウンドルール:2つ設定します。
①カスタムTCP & ポート8080(spring boot接続用)
②カスタムTCP & ポート22(Tera Term接続用)

入力が完了したら「セキュリティグループの作成」を押下します。

EC2インスタンスの作成

EC2 > インスタンスを選択します。

「インスタンスを起動」を選択

設定をしていきます。

Name and tags:好きなインスタンスの名前
アプリケーションおよびOSイメージ:Amazon Linux
キーペア:新しいキーペアを作成。詳しくは以下を参照
セキュリティグループ:先ほど作成したセキュリティグループを選択

【キーペアの作成】
キーペアの名前:好きな名前
キーペアのタイプ:ED25519

キーペアのタイプがRSAだと、後の手順がうまくいきませんでした。
最近仕様が変わったらしいです。

「作成」を押すと「.pemファイル」ができるので、保管します。

入力が完了したら、インスタンスの作成ボタンを押下します。
起動しているのを確認して、次の作業に入ります。

DBを立てる

RDS > データベースを選択します。

データベースの作成を押下します。

設定項目を入力していきます。

データベース作成方法:標準
エンジンのオプション:MySQL
テンプレート:無料利用枠
dbインスタンス識別子:好きな名前
認証情報の設定:dbにログインするユーザー名とパスワードを入力

接続
コンピューティングリソースは「EC2コンピューティングリソースに接続」を選択すると
「EC2インスタンス」という欄が下に出てくるので、それを選択します。

これをすると、自動でインバウンド/アウトバウンド設定をしてくれるので便利です。
後で手動設定することも可能です。

VPC セキュリティグループ (ファイアウォール)は先ほど作ったセキュリティグループを選択します。

追加設定
最初のDBを設定できます。今回は自分で用意した「init.sql」を実行して一気にデータベース作成とサンプルデータ挿入をするつもりなのでスルーしました。

入力が完了したら「データベースの作成」を押下します。

ローカル側の設定

ローカルからEC2に繋ぐ

EC2とローカルを繋ぎます。

繋ぐ方法はいくつかありますが、私が使用しているのはWindowsなので、
Tera Termというツールを使用してローカルからEC2に繋ぎます。

EC2 > インスタンスを選択してインスタンスの詳細を確認し、
インスタンスの「パブリック IPv4 アドレス」をコピーします。

Tera Termを起動して、上記のIPv4アドレスを「ホスト」に貼り付けます。

OKを押下するとセキュリティ警告が出るので続行を押します。

ログイン画面が出るので、ユーザ名のみ入力します。

ユーザ名はDBによって違います。
こちらをご参照ください。

Amazon Linux2の場合は「ec2-user」がユーザー名になります。

認証方式はEC2作成のときに作ったセキュリティキー(.pem)を使用してログインします。

以下の画面になれば成功です。無事にEC2の中に入れています。

jarファイルをEC2にアップロード

PowerShellなどを使用し、
以下コマンドでローカルのファイルをEC2にアップロードします。

scp -i "[pemのパス]" "[jarのパス]" ec2-user@[EC2のエンドポイント]:/home/ec2-user/

Tera Termでlsコマンドを実行してjarファイルが無事に送られてるか確認します。

OKですね!

EC2上で動作確認

EC2上で試しにjarファイルを動かしてみます。

Tera Termで以下コマンドを実行したいのですが、
javaがEC2の中に入っていないのでエラーになります。

java -jar [jarファイル名]

先にjavaをEC2に入れます。
今回は無料のJDKを使います。

以下コマンドで入れていきます。

sudo wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
sudo yum install -y jdk-17_linux-x64_bin.rpm

インストールが終わったらjava -versionでjavaのバージョンが出るか確認します。

これで完了…と言いたいのですが、
まだMySQLに初期データを入れていません。

これだとエラーになるので、
EC2からRDSのMySQLに繋いで初期データを突っ込みます。

まずMySQLに突っ込む用のinit.sqlを作成します。
今回はローカルでdocker用に使っていたものを再利用します。

CREATE DATABASE IF NOT EXISTS sample;

USE sample;

CREATE TABLE IF NOT EXISTS user(
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE
);

INSERT INTO user (name, email) VALUES ("John", "John@gmail.com");
INSERT INTO user (name, email) VALUES ("Nancy", "Nancy@gmail.com");
INSERT INTO user (name, email) VALUES ("Mike", "Mike@gmail.com");

先ほどと同様、まずローカルからEC2インスタンスにSCPコマンドで送ります。

scp -i "[pemのパス]" "[init.sqlのパス]" ec2-user@[EC2のエンドポイント]:/home/ec2-user/

送ったらlsで確認

そしたらMySQLに接続…したいのですが、
MySQLがEC2に入っていないので、MySQLに接続するコマンドが打てません。

先にMySQLをインストールします。

MySQLのインストールはこちらを参照。
GPGキーのエラーが発生するので、こちらの記事を参照して解決。

無事MySQLを入れたら以下コマンドを入力

mysql -h <RDS上のMySQLのエンドポイント> -P <RDSのMySQLのport> -u <username> -p

パスワード聞かれるので設定したパスワードを入力してログイン。

以下コマンドで初期データを挿入

source ./init.sql;

データが挿入できたか確認

OK!

準備が整ったので、jarを起動して動作確認します。
以下コマンドを入力します。

java -jar [jarファイル名]

起動はしたが、DB接続エラーになってしまいました。
そういえばDB接続情報がローカルのままだった…

てことでSpring bootのDB設定ファイル(application.properties)を修正して、再度scpコマンドでEC2に送り、再度トライ。

うまくいきました。
これにブラウザから接続するには、「EC2のエンドポイント:8080」を入力します。

無事、起動しました!

サービスを常駐させる

このままだと、使いたいときに毎回EC2に入って手動で起動しないといけません。
面倒なので、EC2インスタンスが起動したときに自動でjarファイルを起動するようにします。

やり方は以下の手順になります。
①serviceファイルの作成
②systemdへの登録

それぞれ説明していきます。

serviceファイルの作成

常にアプリケーションを起動させる(=常駐させる)には、
アプリケーションを「systemd」に登録する必要があります。

systemdはLinuxシステムのデーモンやサービスを管理するためのツールで、
アプリケーションの起動、停止、自動再起動などを行うことができます。

/etc/systemd/system配下に、アプリケーションの起動設定ファイルを作成します。
今回は「myapp.service」という名前で作成しました。

sudo vi /etc/systemd/system/myapp.service

アプリケーションの概要や環境変数などを記述し、
「サービス」としてsyatemdに登録します。

[Unit]
Description=Java&React App    #サービスの説明
After=syslog.target  #システムのログが使用可能になってからサービスを起動
After=network.target   #ネットワークが使用可能になってからサービスを起動

[Service]
User=ec2-user
WorkingDirectory=/home/ec2-user
Environment="JAVA_HOME=/opt/jdk-17"
Environment="SPRING_DATASOURCE_URL=jdbc:mysql://[RDSのエンドポイント]:3306/[繋ぎたいDB名]"
Environment="SPRING_DATASOURCE_USERNAME=[DB接続用のユーザー]"
Environment="SPRING_DATASOURCE_PASSWORD=[DB接続用のパスワード]"  
ExecStart=/opt/jdk-17/bin/java -jar /home/ec2-user/otameshi-0.0.1-SNAPSHOT.jar    #アプリを実行する
Restart=always  #うまく起動できなかった場合、アプリは自動で再起動する(100秒間で5回以上起動できなかったら諦めるので無限ループにはならない)

[Install]
WantedBy=multi-user.target  #マルチユーザーモード(複数の人がこのEC2に接続できる状態)にしておく

※Environment=の箇所は、jarファイルで直接DBへの接続情報を指定している場合は書かなくても問題無く動きます。しかし、環境変数は切り離して管理した方がセキュリティが向上する為、EC2で管理しておいて、それをjarから参照する方が良いとされています。

▽デーモンを再起動し、設定を反映させます。

sudo systemctl daemon-reload

▽サービスを起動します。

sudo systemctl start myapp

▽起動確認をします。
緑の◯が表示されていれば問題無く起動しています。

sudo systemctl status myapp

▽サービスを自動起動するよう設定します。

sudo systemctl enable myapp

動作確認

これでEC2インスタンス上でjarファイルが自動起動し、
常にアプリケーションにアクセスすることができるようになりました。

http://[EC2のパブリックアドレス]:8081 にアクセスすると…

出ました!
データ取得ボタンを押すと…

ちゃんとデータが取れていますね。ナイス!

さいごに

この後の流れとしては、
ローカルで開発→ビルド→EC2にアップロード→jarファイルの差し替え
を繰り返していけば、アジャイル的な開発ができます。

今はhttpなので、httpsにする & DNSはRoute53あたりで設定して
https://nakanishi.jpとかでアクセスできるようにしたいな~。

まぁnakanishi.jpはすでに取られてるんですけどね。
何か似たアドレスにしよーっと。

今回は EC2×RDS で実装していましたが、
chatGPTに聞いたらもっと沢山のAWSのサービスを使用したら簡単に実装できるらしいので
今後やっていこうと思います。

今回はここまで!
Enjoy Hacking!!