AWS EC2 にLaravelをデプロイする

# はじめに
AWS RDS でデータベースを作成し、
AWS EC2 に Laravelをデプロイする方法をまとめた。

# 開発環境
PHP7.4　Laravel8.x　mysql8.0

# 事前準備
AWSでEC2インスタンスとRDSインスタンスを作成する

## EC2インスタンス
1. 名前を付ける
    <br>

1. アプリケーションおよびOSのイメージ
    Amazon Linux AMI(HVM)を選択
![EC2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/0d238316-1be0-dea9-7405-abcd0e71fed4.png)
    <br>

1. インスタンスタイプ
    変更しない
    <br>
    
1. キーペア(ログイン)
    選択もしくは作成
![EC2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/0b2f43b7-ec59-3bbf-792a-1b5c3ce81f23.png)
    <br>
    
    作成する場合、以下の設定にする
![EC2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/82f42214-1524-1d44-f5c8-301cad363ec0.png)
    <br>

1. ネットワークを設定
    セキュリティグループを作成する
![EC2-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/13c90a10-b6c3-b473-026a-75672520aea7.png)
    <br>
    
1. ストレージを選択
    変更なし
    <br>

1. 高度な詳細
    変更なし
    <br>

1. 概要
    変更なし
    <br>

1. インスタンスを起動
    「インスタンスを起動」ボタンをクリック
    <br>
 
## RDS
1. データベース作成方法、エンジンのオプションを選択
    標準作成を選択
![RDS-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/cf7ed917-8202-1782-031a-d47e799ef0b3.png)
    <br>
    エンジンバージョンはプロジェクトと同じもしくは近いものを選択
    ![RDS-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/f5916b17-8d02-95d6-2166-3ce5182a950e.png)
    <br>
    
1. テンプレート
    無料利用枠を選択
    ![RDS-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/4b2139f1-fdb0-661e-c08b-100ebbeb065a.png)
    <br>
    
1. 可用性と耐久性
    変更なし
    <br>
    
1. 設定
    DBインスタンス識別子、マスターパスワードを設定
    ![RDS-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/8b26d340-8929-6a76-785c-4ab718b68766.png)

1. インスタンスの設定
    変更なし
    <br>

1. ストレージ
    変更なし
    <br>

1. 接続
    「EC2コンピューティングリソースに接続」を選択し、ECインスタンスを選択
    ![RDS-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/ad7e1b32-f180-6a58-7392-8e28759fc196.png)
    <br>
    
    DBサブネットグループ 「既存の選択」を選択
    VPCセキュリティグループ(ファイアウォール)「新規作成」
    ![RDS-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/3c81b8c3-d8f9-fcfa-58fa-4142839d04ba.png)
    <br>
    
1. データベース認証
    変更なし
    <br>
    
1. モニタリング
    変更なし
    <br>
    
1. 追加設定
    最初のデータベース名を入力
    ※データベース名を指定しないとデータベースを作成しないため、必ず指定する
    ![RDS-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534893/ffd94f9a-960a-fa41-91e3-affb969778f9.png)
    <br>
    
1. データベースの作成
    「データベースの作成」ボタンをクリック
    
# EC2に接続
コマンドプロンプトを起動し、以下のコマンドを実行する
```bash:cmd
# sshkeyのあるディレクトリに移動
$ cd "選択or作成したsshKeyのディレクトリ"

# 接続（インスタンスに接続->SSHクライアント->例に記載されている部分をコピー）
$ cd ssh -i ~
```

# インストール関連
まず初めに、インスタンスに初めから入っているパッケージ類をアップデートする
## アップデート
```bash:~
$ sudo yum update -y
```
パッケージのアップデートが終わったら、インストールしていく

## nginx
```bash:~
$ sudo amazon-linux-extras install -y nginx1

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

# 起動と確認
$ sudo systemctl start nginx.service
$ sudo systemctl status nginx.service

# インスタンス起動時に自動起動するように設定
$ sudo systemctl enable nginx
```

## PHP
```bash:~
$ sudo amazon-linux-extras install -y php7.4

# アプリに合わせて必要なパッケージをインストールする(例)
$ sudo yum install -y php-bcmath php-mbstring php-xml

# 起動と確認
$ sudo systemctl start php-fpm.service
$ sudo systemctl enable php-fpm.service
$ sudo systemctl status php-fpm.service

# インスタンス起動時に自動起動するように設定
$ sudo systemctl enable php-fpm
```

::: note warn
アプリに合わせたパッケージについて
ライブラリなどによって必要なモジュールが変わる場合があるので、環境に合わせてインストールする。足りなかった場合はcomposer installした際にエラーで足りないモジュールを教えてくれるので、そこでインストールしてもOK
:::

## MySQL
デフォルトで入っているMariaDBをアンインストールした後、MySQLをインストールする
### MariaDBをアンインストールする
```bash:~
# MariaDBが入っているか確認
$ sudo yum list installed | grep mariadb

# アンインストール
$ sudo yum remove -y mariadb-libs
```

### MySQLをインストール
mysqlリポジトリをダウンロードする
```bash:~
$ sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm -y
```
GPG鍵を更新する
```bash:~
$ sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
```
再度パッケージのアップデート(これをしないとmysqlがインストールできなかった)
```bash:~
$ sudo yum update -y
```
mysqlをインストールする
```bash:~
$ sudo yum install -y mysql-community-server
```

起動
```bash:~
$ sudo systemctl start mysqld.service
$ sudo systemctl status mysqld.service

# インスタンス起動時に自動起動するように設定
$ sudo systemctl enable mysqld.service
```

## composer
公式にあるコマンドを順番に実行する

https://getcomposer.org/download/

```bash:~
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
```
```bash:~
$ php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
```
```bash:~
$ php composer-setup.php
```
```bash:~
$ php -r "unlink('composer-setup.php');"
```
パスを通す
```bash:~
$ sudo mv composer.phar /usr/local/bin/composer
```
一応バージョン確認
```bash:~
$ composer --version
```

## Git
```bash:cmd
$ sudo yum install -y git
```

# 接続設定
各種設定ファイルを編集していく

## php-fpm
```bash:cmd
$ sudo vi /etc/php-fpm.d/www.conf

"i"を押してinsertモードにし、以下の部分を修正

    #24行目あたり
    user = apache -> user = nginx
    #26行目あたり
    group = apache -> user = nginx 

    # 48行目あたり
    ;listen.owner = nobody -> listen.owner = nginx
    # 49行目あたり
    ;listen.group = nobody -> listen.group = nginx
    #50行目あたり
    ;listen.mode = 0660 -> listen.mode = 0660
    
"esc"でnomalモードにして、":wq"で保存して終了
```

再起動する
```bash:cmd
$ sudo systemctl restart php-fpm.service
```

## nginx
```bash:cmd
$ sudo vi /etc/nginx/nginx.conf

"i"を押してinsertモードにする

　～　省　略　～
    
    http {
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        
        access_log  /var/log/nginx/access.log  main;
        
        sendfile            on;
        tcp_nopush          on;
        tcp_nodelay         on;
        keepalive_timeout   65;
        types_hash_max_size 4096;
        
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
        
        # Load modular configuration files from the /etc/nginx/conf.d directory.
        # See http://nginx.org/en/docs/ngx_core_module.html#include
        # for more information.
        include /etc/nginx/conf.d/*.conf;
        
        server {
            listen       80;
            listen       [::]:80;
            server_name  _;
※　編集　　 root         /var/www/[アプリディレクトリ名]/src/public;
            
        
※ 以下を追加する
        
            add_header X-Frame-Options "SAMEORIGIN"; 
            add_header X-Content-Type-Options "nosniff";
            
            index index.php;
            
            charset utf-8;
            
            location / {
                try_files $uri $uri/ /index.php?$query_string;
            }
            
            location ~ \.php$ {
                fastcgi_pass   unix:/run/php-fpm/www.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }
            
            location ~ /\.(?!well-known).* {
                deny all;
            }
        
※ ここまで
        
            # Load configuration files for the default server block.
            include /etc/nginx/default.d/*.conf;
            
            error_page 404 /404.html;
                location = /404.html {
            }
            
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
        }
    }
    
"esc"でnomalモードにして、":wq"で保存して終了
```

設定をチェックし、再起動する

```bash:~
$ sudo nginx -t
$ sudo systemctl restart nginx
```

## AWS RDS データベース接続確認
```bash:~
# 接続
$ mysql -h "RDSで作成したDBをクリック->エンドポイントをコピー" -P 3306 -u admin -p

パスワードを求められるので、DB作成時に設定したパスワードを入力

# 確認
mysql> show databases;

# RDS作成時に最初のデータベース名を指定していた場合、反映されている。
# データベース名を指定していなかった場合は、mysql内で作成
mysql> CREATE DATABASE データベース名;
```

# プロジェクトの設定
## gitリポジトリをcloneする
```bash:~
# gitのユーザー名とEmailアドレスを設定
$ git config --global user.name "ユーザー名"
$ git config --global user.email メールアドレス ※""はいらない

$ mkdir /var/www
$ cd /var/www
```
権限設定後、clone
```bash:/var/www
$ sudo chown ec2-user:nginx .
$ sudo chmod 2775 .
$ sudo usermod -a -G nginx ec2-user

# デプロイしたいLaravelプロジェクトをclone
$ git clone "githubのURL"
```

## 環境変数の設定
```bash:/var/www/[アプリディレクトリ名]/src
# .env.exampleをコピー
$ cp .env.example .env
$ sudo vi .env

# APPの設定
    # デバッグモードをfalseにする
    APP_DEBUG=false

# DBの設定
    DB_CONECTION=mysql
    DB_HOST=[RDSで作成したデータベースのエンドポイントをコピー]
    DB_PORT=3306
    DB_DATABASE=[RDS作成時に指定した"最初のデータベース名"]
    DB_USERNAME=admin
    DB_PASSWORD=[RDS作成時に設定したパスワード]
    
    ※その他、メール等編集する必要があればする
```

## パッケージのインストール
```bash:/var/www/[アプリディレクトリ名]/src
$ composer install
```

## APP_KEY 作成
```bash:/var/www/[アプリディレクトリ名]/src
$ php artisan key:generation
```

## /config/database.phpファイル
```bash:/var/www//[アプリディレクトリ名]/src
$ sudo vi config/databases.php

# '※'部分の第二引数は記述しなくてOK
    'default' => env('DB_CONNECTION','mysql'),
    'mysql' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        'host' => env('DB_HOST',''), ※
        'post' => env('DB_PORT',''), ※
        'database' => env('DB_DATABASE',''), ※
        'username' => env('DB_USERNAME',''), ※
        'password' => env('DB_PASSWORD',''), ※
        'unix_socket' => env('DB_SOCKET', ''),
        '(charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => null,
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],
```

## DBをマイグレーションする
```bash:/var/www//[アプリディレクトリ名]/src
$ php artisan migrate
```

## 参考記事
参考にさせていただきました。ありがとうございます。

https://qiita.com/yyy752/items/b9d7674fc349f669e801

## おわりに
初めてAWSでデプロイ作業を行ったのでまとめた。
まとめるとサーバー関連が少し理解できた気がする。