【AWS初学者向け】EC2にLaravelアプリケーションをデプロイ

# はじめに
こんにちは、東京でバックエンドエンジニアやってるoonoです。
今回は**AWSのEC２上にアプリケーションをデプロイしてみたい**方向けに
記事を書いていこうと思います。

記述内容に誤りがございましたらご教示いただけますと幸いです。

# 前提知識
本記事は以下のような方を想定しています。
* ローカルで作成したアプリをサーバーにデプロイして公開したい方
* AWSのサーバー（EC2）へのデプロイを行なったことが無い方
* LaravelのCRUD基本知識が身についている方（本記事はLaravelを例に扱ってます）
* Linuxの基礎的なコマンド（cd,ls,mkdirなど）を理解している方
* githubを扱ったことがある方

# 本記事にて扱わない技術
本記事はAWSを扱うのが初めての方に向けての内容となります。
極力シンプルな内容にするため以下のような技術は割愛させていただきます。
* Docker
* docker-compose
* ECS
など、実務レベルに近いアプリのデプロイや運用に関する技術

# EC2とは?
では早速Laravelアプリケーションをデプロイしてweb上に公開していこう！
の前に、今回扱うAWSのサービスである**EC2**について少し押さえておきましょう。

EC2とは、AWSが提供しているクラウドサーバーのサービスです。
AWSの他のサービスもそうですが、EC2は国内・国外様々な場所に配備されており（この単位をアベイラビリティゾーンといいます）、基本的に自分の居場所から物理的に距離が近い場所を選択します。私の場合は東京リージョンです。

AWSが提供するサーバーがEC2とのことですが、手軽にサーバーを利用できるレンタルサーバーも国内には色々あります。
（お名前.com、さくらレンタルサーバー、conohaVPSなど）
「サーバーとして動く」という観点ではAWSとレンタルサーバーは変わりません。ただ、両者以下のような違いがあります。

|  | EC2 | レンタルサーバー |
|:-:|:-:|:-:|
|料金| 従量課金性（無料枠あり）  |  月額固定 |
| カスタマイズ性 | 柔軟にできる  | 制限あり  |
| スペック |  ユースケースに合わせて選択可能 | 選択肢が限られている  |

EC2の方が良い風に見せてますが、もちろん両者トレードオフなので、メリット・デメリットはあります。ただ基本的に何かしらのプロダクトをデプロイするとなった場合にはクラウドサーバー（AWS）を選択するのが常なのかと思います。

EC2について詳しく知りたい方は[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/concepts.html)をご覧ください。

# 手順
今回は以下の手順でEC2にアプリケーションのデプロイを行なっていきます。
1. VPCを作成
1. EC2インスタンスを起動
1. 作成したEC2にSSHログインし、Laravelアプリケーションのプロジェクトを作成
1. 該当のURLにアクセスし、アプリケーションが起動していることを確認

# VPCを作成
EC2へのデプロイにあたり、まずはVPCを作成していきます。VPC（Virtual Private Cloud）とは、「EC2はこの領域内で動いてるよ！」を定義するのに必要な領域のことです。
詳しくは[公式](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)をご参照ください。

では早速VPCを作成します。

VPCのマネジメントコンソールに移動し、VPCを新規作成
![スクリーンショット 2024-04-07 16.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/07193f6f-bd9a-0766-f54e-82896969aea6.png)


作成するリソースを「VPCなど」にするとVPC内の[サブネット](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/configure-subnets.html)も同時に作成できます。
![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/3364507/c483d887-6a62-3609-e973-874b6eee2b81.png)


各設定値を下記画像のように設定してください。
![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/3364507/80326f4e-7a89-112d-8ce2-1dda00c7ee5e.png)


「VPCを作成」ボタンをクリックしてVPCを作成します。
![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/3364507/95a0a70f-c9f8-b0db-5732-a250d985a4b2.png)


作成したVPCが一覧に表示されます。私の場合、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/3364507/d207e37e-dcc9-1fd3-69d0-f0f19d018c66.png)


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/3364507/039f283b-2d24-3cac-7d59-9a64c387aa58.png)


VPCの作成はこれで完了です！

# EC2を作成
次にECを作成していきます。
マネジメントコンソールからEC2の操作画面へ移動し、右上の「インスタンスを起動」ボタンから新規作成します。
![スクリーンショット 2024-03-29 6.39.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/370aa7af-2e17-0a79-beeb-5291ec80289c.png)

以下の設定を選択します。
* 名前とタグ：任意の名前を入力
* Amazonマシンイメージ（AMI）:Amazon Linux 2023
* インスタンスタイプ:t2.micro
* キーペア：新規作成（後述します）
* ネットワーク設定
  * VPCおよびサブネットは前項で作成したリソースを選択
  * パブリックIPの自動割り当て：有効化
  * 「セキュリティグループを作成」を選択
  * その他の項目はデフォルトでOKです

上記設定したらインスタンスを起動します
![screencapture-ap-northeast-1-console-aws-amazon-ec2-home-2024-04-08-19_53_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/6ec35b29-bfd6-21ce-14bf-69316cf7a5e6.png)

途中にキーペアを作成するステップがありますが、これはサーバーにSSHという方法でログインするために
必要な情報ですので、自動ダウンロードされるpemファイルは大切に保管しましょう。
![スクリーンショット 2024-04-08 19.45.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/10316863-9e69-b208-1469-6b5675df4eb1.png)

インスタンスを起動できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/7169952c-a1bf-df17-29e3-e23de6c867d4.png)

# EC2インスタンスに接続
作成したEC2インスタンスに接続してLaravelのアプリケーションをデプロイしていきます。（もう少しです、頑張っていきましょう！）

### マネジメントコンソールから接続
EC2のマネジメントコンソールからEC2へ接続することができます（便利!）

対象のEC2インスタンスにチェックを入れ。上部の接続ボタンをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/7ee64c58-09ae-5ba6-826c-d67a487b251e.png)

入力値は変更せず、接続ボタンクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/b536c8f3-b203-093d-ae9b-18eba0f5f4b7.png)

EC2インスタンスの接続に成功し、コンソール画面が起動します！
ここでデプロイ準備するためのコマンドをカタカタ叩いていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/dc47a418-6b99-95a8-5e42-3a8deb3f7d59.png)

### LAMP環境の構築
EC2にLAMP環境の構築を行なっていきます。LAMPとは
* L: Linux
* A: Apache
* M: MySQL（今回はDB接続を行わないため割愛します）
* P: PHP or Python

の環境構築技術の頭文字をとった言葉です。[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/ec2-lamp-amazon-linux-2023.html)を参考に構築します。
順に以下のコマンドを入力していきます。

```
sudo dnf update -y
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/59d418d1-ad69-7cf7-abdb-25b89a65e900.png)


```
sudo dnf install -y httpd wget php-fpm php-mysqli php-json php php-devel
```
たくさん出力され、実行に少し時間がかかりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/87264cb8-c6c2-d76f-418c-62669c62fc2d.png)

Apache（EC2をweb　サーバーとして稼働させるためのソフトウェア）を起動します。このコマンドは実行しても結果は出力されません。
```
sudo systemctl start httpd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/55f74507-fd4b-98cb-5252-503ecfe46500.png)

サーバーの起動時にApacheも自動で起動するように設定
```
sudo systemctl enable httpd
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/8d4bad85-f63b-4dc8-f199-f6fc70933100.png)

Apacheの起動確認です。「enabled」が出力されればOKです
```
sudo systemctl is-enabled httpd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/9a018566-8147-8cc0-45d4-eec4f47c093b.png)


### Composerをインストール
続いて、PHPパッケージ管理ツールの[composer](https://getcomposer.org/)をインストールします。
下記のコマンドを順に入力します。

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/a3d894f2-22e6-d95f-82ed-d28f6f2e224d.png)

```
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/8cb6646a-3a61-fd2a-3a6c-a8d2e5c9f1f3.png)

```
php composer-setup.php
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/9535b464-e66d-cfd9-8391-34700f030e7b.png)

```
php -r "unlink('composer-setup.php');"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/d4d31a14-2d05-9f96-c89c-a2a6479aac86.png)

```
sudo mv composer.phar /usr/local/bin/composer
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/231f43b1-ba77-512f-9f96-b5d017fef97c.png)

最後にcomposerコマンドが使用できるか確認します。画像のように出ていれば問題ありません。
```
composer -v
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/94142981-f14a-5cc1-994c-2132fdb53d33.png)



# Laravelアプリケーションのプロジェクトを作成
いよいよアプリケーションを準備していきます。あまり本題とは関係ないので、Laravelの仕様には踏み込みません。

### プロジェクト作成
/varディレクトリに移動します
```
cd /var
```
現在の状態でcomposerコマンドを使用するにはsudoが必要なので、sudoなしでcomposerコマンドにてプロジェクト作成できるように設定します
```
sudo chmod 777 www
sudo chmod -R 775 /usr/local/bin/composer
sudo chown -R ec2-user:ec2-user /usr/local/bin/composer
```
/var/www内でプロジェクト作成します
```
cd www
```

「deploy-sample」というプロジェクト名で作成
```
composer create-project laravel/laravel:^11.0 deploy-sample
```
色々出力され、プロジェクトが作成されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/c177e8b2-2323-cdac-1568-a6b0d76600c1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/142d3930-a07c-e4c2-c9dd-0d73537e800d.png)


### ルートディレクトリを変更
Laravelではアクセスがきたら最初に「プロジェクトフォルダ/public/index.php」を見に行くので、ドキュメントルートを/var/www/deploy-sample/publicに変更します。

Apacheの設定ファイルを編集し保存
```
sudo vi /etc/httpd/conf/httpd.conf
```
* Allow Overrideを「ALL」に変更
* Document Rootを「/var/www/deploy-sample/public」に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/ad80d603-32f2-314b-2c34-e74787a74a3e.png)

Apacheを再起動
```
sudo systemctl restart httpd.service
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/2fda009a-cbb4-83de-f927-d45e26d584a2.png)

プロジェクトフォルダに移動し、アプリが起動することを確認します。
```
cd deploy-sample
```
```
php artisan serve
```

以下のようになれば起動成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/663f302a-032e-0b50-34e7-acdb7ee4ef08.png)

以下にアクセスします。
http://ec2のパブリックIPアドレス

エラー出ちゃいましたね、、logファイルへの書き込み権限をアプリケーションに付与しなければいけません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/ac4d36e4-a09d-057d-2d95-da83b8029e73.png)

logファイルへの書き込み権限を設定
```
sudo mkdir -p storage/framework/cache/data/ && \
sudo mkdir -p storage/framework/app/cache && \
sudo mkdir -p storage/framework/sessions && \
sudo mkdir -p storage/framework/views && \
sudo mkdir -p storage/logs && \
sudo chmod -R 775 storage/framework/sessions && \
sudo chown -R apache:apache storage/framework/sessions && \
sudo chmod -R 775 storage/framework/views && \
sudo chown -R apache:apache storage/framework/views && \
sudo chown -R apache:apache storage/logs/ && \
sudo chown -R apache:apache storage/framework/cache/data/
```
これで上記のエラーは対応できました。

### データベースの用意
さて、あとはデータベースを用意できればアプリケーションが起動されます。AWSでデータベースを使用するためにはRDSというサービスを使用します。データベース自体の定期的なアップデート等、面倒はAWSが見るから開発者はそこらへん気にしなくていいよ！ていうサービスです（うれしい！）

しかしRDSの手順も記載すると長くなるので、[こちら](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.MySQL.html)を参考に進めてみてください。（MySQLのデータベースを使用します）

セットアップができたら.envには以下の記述を追加してください。
```.env
DB_CONNECTION=mysql
DB_HOST=作成したRDSのエンドポイントを入力
DB_PORT=3306
DB_DATABASE=RDS作成時に入力したデータベース名
DB_USERNAME=RDS作成時に入力したユーザー名
DB_PASSWORD=RDS作成時に入力したパスワード
```
上記完了したら、EC2のコンソールに戻り、以下コマンドを実行
```
php artisan migrate
```
上記コマンドにてLaravelアプリケーションを起動するのに必要なテーブルのセッテイングがされました。

:::note info
データベースは必ずしもRDSを使用する必要はありませんが、現場でAWSでアプリケーションを構築する際はRDSは頻繁に選択されるケースのため、実務を想定するならRDSでの構築に慣れておくといいでしょう。
:::


では、再度`http://ec2のパブリックIPアドレス`にアクセスしてみましょう。
![スクリーンショット 2024-03-29 6.29.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/c1aa8283-7216-aa84-2d9c-3984f84f0708.png)

起動完了です！！IPアドレス載せないため添付画像のURLは僕のローカルですが、みなさんもこの画面が確認できるかと思います。

# まとめ
いかがでしたでしょうか？今回の内容はAWSでアプリケーションを構築する際の一番ベーシックになる部分なので、ぜひここは押さえてレベルアップしていきましょう！！
また、誤っている箇所がございましたらご指摘お願いいたします。