🎮

EC2にLaravelプロジェクトをデプロイしてUnityからAPI呼出し

2024/07/17に公開

背景

学生がクライアントサイド:Unity、サーバーサイド:Laravelで実装するソーシャルゲームを開発することにしたため、できるだけモダンな環境の方がいいかなということで、ゆくゆくはそれをAWSへデプロイしてUnityからAPI叩いて動かせたら良いよね、という話を提案

私自身は元WebエンジニアではあるもののAWSに関してはド素人だったのでソシャゲ部分はUnity/Laravel共にログインやユーザー周りなど簡単な部分のみを実装してEC2へのデプロイを目標にまずは自分も勉強がてらやってみることに
(似たような記事はたくさん出回っているが自分の環境で出来たということを残すのが趣旨)

前提

ローカルの環境は以下の通り

  • サーバー
    • Laravel 10.48.16
    • PHP 8.2.13
    • MySQL 8.0.32
  • クライアント
    • Unity 2022.3.10

・AWSでの環境構築について色々考えていると、Webサーバーってどうなってたっけ?と気づく
ローカルではLaravel SailによるDockerコンテナでの環境構築をしていたためsail upでなんとなくサーバーが起動していたが、それだとPHPビルトインWebサーバーで動いているだけだった
今回はWebサーバーとしてnginxを採用することに

・ソースはGitHub上で管理しているので、プロジェクトはクローンして持ってくる

・今回はとりあえずRDSは使わず、MySQLも全てEC2上で完結させることにした

AWSアカウント登録

以下記事を参考に登録
連絡先情報は半角英数字での入力のため、住所などは入力の仕方に注意
https://www.cloudbuilders.jp/articles/438

AWSマネジメントコンソールへログイン

まず画面が開いたら右上のリージョンがシドニーになっていたので東京に変更した

左上の[サービス]から コンピューティング > EC2 を選択してEC2のダッシュボードを開く(ついでに★でお気に入り登録してみた)

インスタンス作成

ダッシュボード左側のメニューから インスタンス を選択し、
オレンジの「インスタンスを起動」ボタンを押す

名前はインスタンスの名前を入力
なんでもいいのでわかりやすい名前にしておく

AMI(Amazonマシンイメージ)の選択

今回は検証用なのでとりあえずデフォルトで無料枠対象のAmazonLinux2023を使用
インスタンスタイプもt2.microで進めてみる

キーペアの作成

「新しいキーペアの作成」を選択して作成する

キーペア名はわかりやすいものを適当につける
キーペアのタイプはとりあえずRSAをそのまま選択
プライベートキーファイル形式は、今回はPuTTYで接続したいので[.ppk]を選択
(ここは接続したい環境に合わせて選択を)

「キーペアを作成」をクリックすると指定した形式のプライベートキーがダウンロードされる
SSH接続時に使うのでわかりやすい場所に保存するなど管理はしっかりと

作成するとプルダウンで作成したキーペアが選択される(はず)

ネットワーク設定・ストレージ設定

HTTPとHTTPSのトラフィックを許可して他は特に変えなかった

ストレージ設定もとりあえずそのまま8GBで(無料利用枠は30GBまで)


他はそのままで「インスタンスを起動」ボタンを押して
EC2インスタンスの作成が完了😎

PuTTYでSSHログイン

インスタンスのダッシュボードから先ほど作成したインスタンスを選択して「接続」ボタンを押す

SSHクライアントで接続したいのでSSHクライアントのタブを選択し、手順を確認する

PuTTYであれば上記の説明にあまりあてはまらないかも😇
HostNameにec2-から始まるホスト名を入力し、
SSH > Auth の項目に生成したppkを設定して接続する
(ホスト名はインスタンス情報の「パブリック IPv4 DNS」でも確認できる。同画面の「パブリック IPv4 アドレス」でも接続できると思う(試してはいない))

ログインはec2-userで可能

もしくは接続ボタンを押した時に開いているであろう「EC2 Instance Connect」というツールを使うことでブラウザからSSH接続して直接アクセスできる機能もあるので、面倒ならそちらでも可

色々インストールしていく

最初に念の為パッケージ類のアップデート

$ sudo dnf update

nginxインストール

$ sudo dnf install nginx

# バージョン確認
$ nginx -v

# 自動起動の設定
$ sudo systemctl enable nginx.service

# サーバー起動
$ sudo systemctl start nginx.service

# 起動状態確認コマンド
$ sudo systemctl status nginx.service

# 動作確認コマンド
$ curl -s http://localhost | grep title

## 以下が表示されたらOK
<title>Welcome to nginx!</title>

インスタンスの概要画面にあるパブリックIPv4アドレスか、パブリックIPv4DNSのアドレスにアクセスすると以下の画面が出るはず

PHPインストール

PHPと関連パッケージをまとめてインストールしていく

$ sudo dnf install  php-fpm php-mysqli php-json php8.2 php-devel

# バージョン確認
$ php -v
$ php-fpm -v

PHPは念の為8.2を指定した

Composerインストール

公式サイトにあるコマンドを実行
https://getcomposer.org/download/

$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"

# パスを通す
$ sudo mv composer.phar /usr/local/bin/composer
# バージョン確認 
$ composer --version

MySQLインストール

$ sudo dnf localinstall https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm -y
$ sudo dnf install mysql-community-server

上記2行目(mysql-community-serverのインストール)で以下のようなエラーが出る可能性がある

Public key for mysql-community-client-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-client-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
Public key for mysql-community-client-plugins-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-client-plugins-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
Public key for mysql-community-common-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-common-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
Public key for mysql-community-icu-data-files-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-icu-data-files-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
Public key for mysql-community-libs-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-libs-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
Public key for mysql-community-server-8.0.38-1.el9.x86_64.rpm is not installed. Failing package is: mysql-community-server-8.0.38-1.el9.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022
The downloaded packages were saved in cache until the next successful transaction.
You can remove cached packages by executing 'dnf clean packages'.
Error: GPG check FAILED

上記エラーが発生したら以下コマンドを実行してから再度mysql-community-serverをインストールする

$ sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023
$ sudo dnf install mysql-community-server

さらに追加でやっておくコマンド

# MySQL自動起動設定
$ sudo systemctl enable mysqld.service

# MySQL起動
$ sudo systemctl start mysqld.service

# MySQL起動確認
$ sudo systemctl status mysqld.service

MySQL接続

まずは初期パスワードを確認する

$ sudo grep 'temporary password' /var/log/mysqld.log

#表示される末尾のlocalhost:の後がパスワード
A temporary password is generated for root@localhost:{パスワード}

パスワードが確認できたら接続する

$ mysql -u root -p
Enter password: {パスワード}

mysql >

接続できたらexitで一旦抜けておく(パスワードを変更する場合)

MySQLパスワードの変更

$ mysql_secure_installation

Securing the MySQL server deployment.

Enter password for user root: {パスワード}

The existing password for the user account root has expired. Please set a new password.

New password: {新しいパスワード}

Re-enter new password:
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
Using existing password for root.

# パスワードの強度が表示、rootパスワードを変更するかの確認
Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : Y

New password: {新しいパスワード}

Re-enter new password: {新しいパスワード}

Estimated strength of the password: 100
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : Y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y
Success.

All done!

途中で色々聞かれるが基本的にはYを返している
パスワードが変わったか確かめたい場合は再度rootで接続してみる

データベース作成

パスワードを変えたら再接続してデータベースを作成する

$ mysql -u root -p
Enter password: {新しいパスワード}
$ create database [データベース名];
# 作成できたか確認する場合は
$ show databases;

exitで抜けておく

Gitインストール

$ sudo dnf install git -y

# フォルダ権限変更、実行権限変更
$ sudo chown ec2-user:nginx /var/www
$ sudo chmod 2775 /var/www
$ sudo usermod -a -G nginx ec2-user

/var/wwwフォルダは以下の権限になる
drwxr-xr-x. 4 ec2-user nginx xx Jan x dd:mm www

LaravelアプリをEC2に配置

Gitクローン

$ cd /var/www/
$ git clone https://github.com/xxxxx/[アプリ名].git

GitHubのクローンのURLはhttpsのもので良い
今回クローンしようとしたのがprivateリポジトリだったため、
認証情報(ユーザ名とパスワード)の入力を普通にやっても案の定ダメだった
この場合、パーソナルアクセストークンを作成する必要がある

GitHubの Setting > Developer Settingから Personal access token > Tokens(classic)を選択し、 Generate new token ボタンを押して作成する

Noteにはトークン名をつける
Expirationはトークンの有効期限  今回は一旦無期限にしている
(GitHub的には有効期限設定することをオススメされる)
repoにチェックを入れて、Generate Tokenで作成

次のページにトークンが表示されるので、確実にコピーする(右側にコピーボタンもある)
作成されたトークンをパスワード代わりに使うことで認証ができるのでもう一度クローンを試す

$ git clone https://github.com/xxxx/hogehoge.git
Cloning into 'hogehoge'...
Username for 'https://github.com': USERNAME
Password for 'https://USERNAME@github.com': {ここに作成したトークン}
remote: Enumerating objects: 251, done.
remote: Counting objects: 100% (251/251), done.
remote: Compressing objects: 100% (169/169), done.
remote: Total 251 (delta 81), reused 224 (delta 58), pack-reused 0
Receiving objects: 100% (251/251), 109.48 KiB | 7.82 MiB/s, done.
Resolving deltas: 100% (81/81), done.

.envファイルの更新

そもそも.envファイルが無かったので.env.exampleをコピーして作成

$ cd [アプリフォルダ名]
$ cp .env.example .env
$ sudo vi .env

viを使って.envの中身を更新する
主な更新箇所は以下の通り

DB_DATABASE=[作成したデータベース名]
DB_USERNAME=root
DB_PASSWORD={DBパスワードを指定}

:wqで保存

composer install

composer.lockがあるディレクトリに移動してから行う

$ cd /var/www/[アプリフォルダ名]
$ composer install --optimize-autoloader --no-dev
$ composer update

アプリケーションキー作成

$ php artisan key:generate

DBマイグレーション

$ php artisan migrate

# テストデータ取り込み(seeder)
$ php artisan migrate:refresh --seed

#ディレクトリの権限変更
$ sudo chmod -R 777 storage

php-fpm調整

設定ファイルなので変更前のコピーをバックアップとして取っておく

# ディレクトリ移動
$ cd /etc/php-fpm.d/

# ファイルコピー
$ sudo cp www.conf www.conf_org

# ファイル編集
$ sudo vi www.conf

変更箇所は以下

user = nginx

# 26行目付近
group = nginx

# 48,49行目付近
listen.owner = nginx
listen.group = nginx

変更が完了したらフォーマットチェック

$ sudo php-fpm -t

# エラーがでなければOK
NOTICE: configuration file /etc/php-fpm.conf test is successful

nginx調整

ディレクトリ移動して先ほど同様バックアップとしてコピーを作ってから編集

$ cd /etc/nginx/

# ファイルコピー
$ sudo cp nginx.conf nginx.conf_org

# ファイル編集
$ sudo vi nginx.conf

変更箇所は以下

# 41行目付近のrootを変更(serverの括弧内)
:
    server {
:
:
        root         /var/www/{アプリ名}/public;
:

# 46行目付近にあるerror_pageの記述を削除(serverの括弧内)
       error_page 404 /404.html;
       location = /404.html {
       }

       error_page 500 502 503 504 /50x.html;
       location = /50x.html {
       }

# 45行目付近にlocationを追加(serverの括弧内)
        location / {
	      try_files $uri $uri/ /index.php?$query_string;
        }

変更が完了したらフォーマットチェック

$ sudo nginx -t

# エラーがでなければOK
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

nginxとphp-fpmを再起動して設定を反映させる

$ sudo systemctl restart php-fpm
$ sudo systemctl restart nginx

これでとりあえずLaravelのURIなどを指定して画面表示が確認できればOK
今回はAPIのみ用意していたので、テスト用にGETのルートを1つだけ追加しておいたのでそこにアクセスしてとりあえず繋がっていることの確認だけ行った

あとはUnity側からURI指定してアクセスしてみるだけ!

Unityからアクセス

Unity側ではURIをローカル環境と開発環境で分けるために、取り急ぎ各APIの定数を作ってdefineの指定で一括切り替えできるようにしておいた (もっと良い方法ありそうだけど)

#define LOCAL_SERVER
//#define DEVELOP_SERVER

public class Uri
{
#if LOCAL_SERVER
    ///<summary>ログイン</summary>
    public const string Login = "http://localhost/api/login";
    ///<summary>アカウント登録</summary>
    public const string Register = "http://localhost/api/register";
#elif DEVELOP_SERVER
    ///<summary>ログイン</summary>
    public const string Login = "http://XXXX/api/login";
    ///<summary>アカウント登録</summary>
    public const string Register = "http://XXXX/api/register";
#endif
}

↑的なクラスを用意していた
で、とりあえずパブリックDNSでアクセスしようとURI貼り付けて実行してみたらhttpだからとエラーで怒られた
これはそもそもhttps対応をするべきだと思うけど、取り急ぎ動作確認したかったのでUnity側の設定でこれを回避することにした

Player Settingの Configuration > Allow downloads over HTTP という項目を「Allowed in development builds」に変更することでhttpでもアクセスが確認できた

これにてUnityエディタ上(クライアント側)でも動作確認完了😎

おわりに

これでひとまずEC2上にLaravelのアプリを乗せてUnity側からAPIアクセスするという当初の目的は果たせた

ただhttps化だったりパブリックIPの件だったりデータベースのRDSだったりまだまだやれること(というかやった方がいいこと)はありそうなので引き続き手探りで調整していきたい

参考記事

https://brainlog.jp/server/aws/post-3246/
https://qiita.com/me-654393/items/504acfbb766eddbf1046

大いに助けられました、というかほぼ使わせていただいてます、感謝しかない🙇

Discussion