【AWS】LaravelアプリをEC2デプロイ

# 0.はじめに
新卒エンジニアが研修中に作成したアプリをデプロイした内容をまとめる為に投稿した記事です。
間違った内容が含まれているかもしれませんがご了承頂ければと思います。
また、その点をコメントでご指摘いただけると幸いです。

# 1.AWS構成図
![スクリーンショット 2022-06-13 10.07.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640019/9570c1f6-dd72-cf31-e84b-8b7454272071.png)

# 2.AWS利用サービス一覧
- EC2
- VPC
- サブネット
- セキュリティグループ
- RDS
# 3.AWS利用サービス設定内容
**1. EC2(パプリックIPアドレスありで、ElasticIPをアタッチする)**
AMI：Amazon Linux 2 Kernel 5.10 AMI 2.0.20220426.0 x86_64 HVM gp2
インスタンスタイプ：t2.micro
ストレージ：1 ボリューム - 8 GiB
インスタンス数：１
**2. VPC**
IPv4 CIDRブロック：10.0.0.0/16
アベイラビリティーゾーン：２
**3. パブリックサブネット**
IPv4 CIDR：10.0.0.0/20
IPv4 CIDR：10.0.16.0/20
**4. プライベートサブネット**
IPv4 CIDR：10.0.128.0/20
IPv4 CIDR：10.0.144.0/20
**5. セキュリティグループ**
インスタンス（アウトバウンドルール）：

|  タイプ  |  プロトコル  |  ポート範囲  |  送信先タイプ  |  送信先  |
| ---- | ---- | ---- | ---- | ---- |
|  全てのトラフィック  |  すべて  |  すべて  |  カスタム  |  0.0.0.0/0  |

インスタンス（アウトバウンドルール）：

|  タイプ  |  プロトコル  |  ポート範囲  |  送信先タイプ  |  送信先  |
| ---- | ---- | ---- | ---- | ---- |
|  SSH  |  TCP  |  22  |  自分のIP  |  自身のIP  |
|  HTTP  |  TCP  |  80  |  カスタム  |  0.0.0.0/0, ::/0  |
|  HTTP  |  TCP  |  80  |  カスタム  |  ::/0  |
|  HTTPS  |  TCP  |  443  |  カスタム  |  0.0.0.0/0  |
|  HTTPS  |  TCP  |  443  |  カスタム  |  ::/0  |

RDS（アウトバウンドルール）：

|  タイプ  |  プロトコル  |  ポート範囲  |  送信先タイプ  |  送信先  |
| ---- | ---- | ---- | ---- | ---- |
|  MYSQL/Aurora  |  TCP  |  3306  |  カスタム  |  インスタンスセキュリティーグループ  |

**6. RDS**
エンジン：MySQL Community（5.7.38）
テンプレート：無料利用枠
インスタンス：db.t2.micro
ストレージタイプ：汎用SSD（gp2）
ストレージ割当：20
ネットワークタイプ：IPv4


# 4.本番環境設定

## 1. nginx

### 1-1. ssh接続
```local
$ ssh -i -i ~/.ssh/(キーペア名.pem) ec2-user@(ElasticIP)
```

### 1-2. yum update
```ec2-user
$ sudo su
$ yum update -y
```

### 1-3. nginxインストール
```ec2-user
$ amazon-linux-extras install nginx1.12 -y
$ nginx -v
=> nginx version: nginx/1.12.2
```

### 1-4. nginx.conf
```ec2-user
vi /etc/nginx/nginx.conf
```

```nginx.conf
==省略===

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name _;
    root /var/www/（リポジトリー名）/public/;
    index index.php;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location /{
        try_files $uri $uri/ /index.php?$query_string;
    }
==省略===
```

## 2. PHP

### 2-1. PHPインストール
```ec2-user
$ amazon-linux-extras install php7.4 -y
$ php -v
=> PHP 7.4.29 (cli) (built: May 12 2022 20:27:52) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

### 2-2. パッケージインストール
```ec2-user
$ yum install php-cli php-pdo php-fpm php-json php-mysqlnd -y
$ yum install php-bcmath php-mbstring php-xml -y
$ yum install php-opcache -y
```



### 2-3.  php-fpm起動
```ec2-user
// php-fpmデーモンをsystemctl経由で起動
$ systemctl start php-fpm
```


### 2-4. Composerインストール
```ec2-user
$ curl -sS https://getcomposer.org/installer | php
$ chown root:root composer.phar
$ mv composer.phar /usr/bin/composer
$ composer -v
=> Composer version 2.3.7
```

## 3. Git

### 3-1. Gitインストール
```ec2-user
$ yum install git -y
$ git --version
=> git version 2.32.0
```

### 3-2. Git clone
```ec2-user
$ mkdir /var/www
$ cd /var/www
$ git clone (リモートリポジトリURL)
$ chmod 777 /var/www/（リポジトリー名）
```


## 4. MySQL
参考記事：https://dev.mysql.com/doc/refman/5.6/ja/linux-installation-yum-repo.html

### 4-1. MariaDBのパッケージ削除
```ec2-user
// mariadb確認
yum list installed | grep mariadb
// mariadb削除
yum remove mariadb-* -y
// mariadb確認
yum list installed | grep mariadb
=> エラー: 表示するパッケージはありません
```

### 4-2.MySQL Yum リポジトリの追加
```ec2-user
yum install https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm -y
// MySQL Yum リポジトリ確認
yum repolist enabled | grep "mysql.*-community.*"
=> 
mysql-connectors-community/x86_64   MySQL Connectors Community            141+51
mysql-tools-community/x86_64        MySQL Tools Community                     90
mysql80-community/x86_64            MySQL 8.0 Community Server               343
```

### 4-3. MySQLインストール
```
$ yum install mysql-community-server
$ service mysqld start
```
補足：「/var/log/mysqld.log」がない場合、「touch /var/log/mysqld.log」で作成する

### 4-4. mysqld自動起動
```
$ systemctl start mysqld.service
$ systemctl status mysqld.service
$ systemctl enable mysqld.service
```

### 4-5. PHP-FPM再起動
```
$ sudo systemctl restart php-fpm
```

### 4-6. MySQL接続確認
```
$ mysql -h (エンドポイント) -u (マスターユーザー名) -p
Enter password:(パスワード)
```

## 5. .env

### 5-1 .env作成
```
$ cd /var/www/リポジトリ名/
$ cp .env.example .env
$ vi .env
```

### 5-2 .env設定
```
+ APP_NAME=アプリ名
+ APP_ENV=production
APP_KEY=
+ APP_DEBUG=false
+ APP_URL=https://(EC2のパブリックIPアドレス)

LOG_CHANNEL=stack

DB_CONNECTION=mysql
+ DB_HOST=エンドポイント
DB_PORT=3306
+ DB_DATABASE=DB名
+ DB_USERNAME=マスターユーザー名
+ DB_PASSWORD=マスターパスワード
```

### 5-3 composer install
```
$ composer install
```

### 5-4 APP_KEY,permission
```
$ php artisan key:generat
$ chmod 755 .env
```

### 5-5 permission
```
$ chmod -R 777 storage
$ chmod -R 777 bootstrap/cache
```

### 5-6 シンボリックリンク設定
```
$ php artisan storage:link
```

### 5-7 nginx 再起動
```ex2-user
systemctl restart nginx
```

# 5. 補足
## エラーログ

```/var/log/nginx/error.log;
2022/06/13 02:02:39 [error] 32466#0: *2 open() "/var/www/（リポジトリ名）/public/login" failed (2: No such file or directory)
```

## 解決方法
```nginx.conf
server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;
    root /var/www/（リポジトリ名）/public/;
    index index.php;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location /{
        try_files $uri $uri/ /index.php?$query_string; // 追記
    }
```



# 6. 参考にした記事
https://sg-report.com/laravel-docker-awsec2-web3/
https://qiita.com/kazumakishimoto/items/0859a5a365b226c1b43a#1-cloudformation
https://www.udemy.com/course/aws-associate/
https://qiita.com/shisama/items/5f4c4fa768642aad9e06
https://dev.mysql.com/doc/refman/5.6/ja/linux-installation-yum-repo.html


# 7. 用語一覧

**インスタンス**
>インスタンスとは、事実、事例、例、場合などの意味を持つ英単語。ソフトウェアの分野では、あらかじめ定義されたコンピュータプログラムやデータ構造などを、メインメモリ上に展開して処理・実行できる状態にしたものを指す。この意味では「実体」と訳されることもある。

https://e-words.jp/w/%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9.html

**AMI**
サービに使うOSのこと（windows OS,Mac OSなど、、）
> AMI は、インスタンスの起動に必要なソフトウェア設定 (オペレーティングシステム、アプリケーションサーバー、アプリケーション) を含むテンプレート

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instances-and-amis.html

**インスタンスタイプ**
CPUやメモリなどの組み合わせのこと
>インスタンスを起動するときは、指定したインスタンスタイプによって、インスタンスに使用するホストコンピュータのハードウェアが決まります。インスタンスタイプごとに、コンピューティング、メモリ、およびストレージの機能が異なっており、これらの機能に基づいたインスタンスファミリーにグループ化されています。インスタンスタイプは、インスタンス上で実行するアプリケーションやソフトウェアの要件に基づいて選択します。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-types.html


**インスタンスファミリー**
インスタンスタイプの用途別のカテゴリーのこと
「t2.micro」であれば「t」がインスタンスファミリー
インスタンスファミリーは5種類に分けることができ、
- 「t2」や「m5」は「汎用」
- 「c5」は「コンピューティング最適化」
- 「r5」は「メモリ最適化」

**インスタンスサイズ**
インスタンスタイプのスペックを示すもの
「t2.micro」であれば「micro」がインスタンスサイズ
種類：「nano」「micro」「small」「medium」「large」「xlarge」「2xlarge」

**キーペア**
公開鍵と秘密鍵のセット
SSH接続するときに必要なキー

**IPアドレス**
ネットワーク機器やWEBサイトなどの場所を特定する為にIPアドレスを利用する
重複が許されない一意の32ビットデータ
ネットワークインターフェースカードに割り当てられている

**IPv4**
IPv4のアドレス総数は2の32乗個、つまり42億9496万7296個
（最大約43億台のコンピュータがインターネットに直接接続できる）


**IPv6**
IPv6ではIPアドレスを128ビットのデータとして表現します。
そのためアドレス総数は3.4×10の38乗個、つまり約340澗（かん）個となります

**CIDR**
>アドレスクラスの概念を気にしないことで、IPアドレスの割り当てや経路選択などの自由度を上げる仕組み

https://wa3.i-3-i.info/word11989.html
注意：既にAWS側で利用されており、設定できないアドレスもある


**CIDR表記**
https://wa3.i-3-i.info/word11990.html


**VPC**
VPCはAWSクラウドのネットワークからユーザー専用の領域を切り出すことができる仮想ネットワークのサービス
> Amazon Virtual Private Cloud (Amazon VPC) を使用すると、定義した仮想ネットワーク内で AWS リソースを起動できます。仮想ネットワークは、お客様自身のデータセンターで運用されていた従来のネットワークによく似ていますが、 AWS のスケーラブルなインフラストラクチャを使用できるというメリットがあります。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html


**サブネットクラス**
ネットワーク内を複数のネットワークに分けたもの（カテゴリー）
メリット：ホストが特定しやすくなる

**EIPとパブリックIPの違い**
共通点：外部からアクセス可能なグローバルIP
インスタンスの再起動を行った際にパブリックIPは変更されるが、グローバルIPを変更されない
注意点：最初に「パブリックIP」の設定をしていない場合でグローバルIPを付与したい場合は、「EIP」による付与のみとなる

**グローバルIPアドレス**
世界で重複の無いIPアドレス
- インターネット上でやり取りに利用されるIpアドレス
- ICANNが管理する

**プライベートIPアドレス**
オフィス内野変えて否などの自分の場所だけで利用されるアドレス
- 利用範囲は限定的な絵エリアだけ

**テナンシー**
クラウドの機器を専有で使う

**アベイラビリティーゾーン**
> アベイラビリティゾーンとは、米アマゾンドットコム（Amazon.com）社のAmazon Web Services（AWS）で、ある地域に立地するデータセンター群を一つの論理的な管理単位にまとめたもの。
https://e-words.jp/w/%E3%82%A2%E3%83%99%E3%82%A4%E3%83%A9%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%82%BE%E3%83%BC%E3%83%B3.html

**ルートテーブル**
ルーティング
どのサブネットがどのインターネットゲートウェイに接続するかを指定する

**インターネットゲートウェイ**
インターネットに接続するための設定を行う

**ネットワークACL**
VPCやサブネットのアクセスを制御する

**セキュリティーグループ**
インスタンス間のアクセスを制御する

**NAT**
プライベートサブネットからインターネットに返信する場合、グローバルIPに変換する必要がある
プライベートアアドレスをグローバルアドレスに変換する仕組みがNAT

**インターネットゲートウェイ**
>インターネットゲートウェイは、VPC とインターネットとの間の通信を可能にする VPC コンポーネント

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html

**amazon-linux-extras**
>amazon-linux-extras とは、Amazon Linux 2 インスタンスにある PHP、Python、Golang、MariaDB などのパッケージをより新しいバージョンで利用できるようマネジメント管理するコマンド。

https://hapicode.com/server/aws-amazon-linux-extras.html