AWS EC2 に Nginx + PHP8 で Laravel8 環境を構築する

AWS EC2 に Nginx + PHP8 で Laravel8 環境を構築する

April 4, 2021

*記事作成時点(2021/4)の手順です。

*DB は RDS を使用する想定です。RDS で DB を構築する手順、Laravel と RDS を接続する手順については本記事では触れません。

*記載の手順は EC2 のインスタンスタイプに関係ありませんが、本手順は t4g にて実施しました。

1. 前作業 #

パッケージのアップデート

sudo yum update -y

2. PHP の環境構築 #

PHP8 が available になっていることを確認。

amazon-linux-extras

PHP8 をインストール。PHP8 が enabled になっていることを確認。

sudo amazon-linux-extras install -y php8.0

インストールされたことを確認。

php -v

PHP8 の拡張モジュール一覧を確認。

sudo yum list php* | grep 8.0

現在インストールされている拡張モジュール一覧を確認。

yum list installed | grep php
php -m

以下が表示された。

  • php-cli.x86_64 8.0.2-1.amzn2 @amzn2extra-php8.0
  • php-common.x86_64 8.0.2-1.amzn2 @amzn2extra-php8.0
  • php-fpm.x86_64 8.0.2-1.amzn2 @amzn2extra-php8.0
  • php-mysqlnd.x86_64 8.0.2-1.amzn2 @amzn2extra-php8.0
  • php-pdo.x86_64 8.0.2-1.amzn2 @amzn2extra-php8.0
  • bz2
  • calendar
  • Core
  • ctype
  • curl
  • date
  • exif
  • fileinfo
  • filter
  • ftp
  • gettext
  • hash
  • iconv
  • json
  • libxml
  • mysqli
  • mysqlnd
  • openssl
  • pcntl
  • pcre
  • PDO
  • pdo_mysql
  • pdo_sqlite
  • Phar
  • readline
  • Reflection
  • session
  • sockets
  • SPL
  • sqlite3
  • standard
  • tokenizer
  • zip
  • zlib

Laravel8 に必要な PHP のバージョン、拡張モジュールは以下の通り。

# Server Requirements

The Laravel framework has a few system requirements. You should ensure that your web server has the following minimum PHP version and extensions:

  • PHP >= 7.3
  • BCMath PHP Extension
  • Ctype PHP Extension
  • Fileinfo PHP Extension
  • JSON PHP Extension
  • Mbstring PHP Extension
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension

https://laravel.com/docs/8.x/deployment#server-requirements

不足しているモジュールを適宜インストールする。

sudo yum install -y php-bcmath
sudo yum install -y php-mbstring
sudo yum install -y php-xml

その他、自身のアプリに合わせて追加でモジュールをインストールする。

sudo yum install -y php-dom
sudo yum install -y php-gd
sudo yum install -y php-intl

処理を高速化するために OPcache をインストールする。

sudo yum install -y php-opcache

インストールされたことを確認。

php -v

PHP-FPM をインストールする。

sudo yum install -y php-fpm

PHP-FPM を起動する。サーバ再起動時も自動起動するよう設定する。その後確認。

sudo systemctl start php-fpm
sudo systemctl enable php-fpm
sudo systemctl status php-fpm

Composer をインストールする。公式サイトに従ってコマンドを実行。

https://getcomposer.org/download/

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

php composer-setup.php

php -r "unlink('composer-setup.php');"

Composer の場所を変える。

sudo mv composer.phar /usr/local/bin/composer

使用できることの確認。Composer のロゴが表示されれば OK.

composer

3. Nginx の環境構築 #

Nginx(nginx1)が available になっていることを確認。

amazon-linux-extras

Nginx をインストール。

sudo amazon-linux-extras enable nginx1
sudo yum install -y nginx

インストールされたことを確認。

nginx -v

Nginx を起動する。サーバ再起動時も自動起動するよう設定する。その後確認。

sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx

この時点でブラウザから IP アドレスを叩くと「Welcome to nginx on Amazon Linux!」が表示される。

4. PHP-FPM と Nginx の接続 #

PHP-FPM の設定ファイルを編集する。(念の為バックアップを取っておくこと)

cd /etc/php-fpm.d/
sudo cp www.conf www.conf_bk_yyyyMMdd
sudo vim www.conf

開いたファイルの以下を変更。

### 24行目あたり ###
# 変更前
user = apache
# 変更後
user = nginx

### 26行目あたり ###
# 変更前
group = apache
# 変更後
group = nginx

### 48行目あたり ###
# 変更前
;listen.owner = nobody
# 変更後
listen.owner = nginx

### 49行目あたり ###
# 変更前
;listen.group = nobody
# 変更後
listen.group = nginx

### 50行目あたり ###
# 変更前
;listen.mode = 0660
# 変更後
listen.mode = 0660

Nginx の設定ファイルを編集する。(念の為バックアップを取っておくこと)

cd /etc/nginx/
sudo cp nginx.conf nginx.conf_bk_yyyyMMdd
sudo vim nginx.conf

開いたファイルの server 部分を以下の通り変更。(「your_project_name」部分は任意の名称)

server {
    listen       80;
    listen       [::]:80;
    server_name  _;
    root         /var/www/your_project_name/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;
}

Nginx を再起動。

sudo systemctl restart nginx

指定したドキュメントルートを作成、ファイルを置いて、表示できることを確認する。

sudo mkdir -p /var/www/your_project_name/public
cd /var/www/your_project_name/public
sudo touch index.html
sudo vim index.html

ファイルを開いたら適当な内容を書き込む。(例)

Hello, World!!

この時点でブラウザから IP アドレスを叩くと書き込んだ内容が表示される。

5. Laravel のデプロイ(GitHub から Pull) #

ブラウザでの表示確認用に作成したファイルとディレクトリは削除しておく。

sudo rm -rf /var/www/your_project_name/

Git をインストールする。

sudo yum install -y git

インストールされたことを確認。

git --version

GitHub に登録する鍵を作成。

ssh-keygen -t rsa

~/.ssh 配下に以下の2ファイルが作成される。

  • id_rsa
  • id_rsa.pub

id_rsa.pub の内容を GitHub に登録する。

cat ~/.ssh/id_rsa.pub

上記で表示された内容を GitHub のリポジトリの、Settings > Deploy keys > Add deploy key より登録。

www フォルダのオーナーを変更する。

sudo chown ec2-user:ec2-user /var/www/

GitHub からプロジェクトを Clone する。

cd /var/www/
git clone git@github.com:your_user_name/your_project_name.git

Laravel のディレクトリに移動後、env ファイルを作成し、Laravel セットアップ関連のコマンド実行。

cd your_project_name
cp .env.example .env
chmod -R 777 storage bootstrap/cache
composer install --optimize-autoloader --no-dev
php artisan key:generate
php artisan storage:link
php artisan config:cache
php artisan view:cache
php artisan migrate:fresh

※ ルーティングファイルをキャッシュさせるコマンドとして「php artisan route:cache」もある。ただし(コントローラに処理を振り分けず)ルーティングファイル内でクロージャを用いて直接処理を完結させている記述がある場合には、このコマンドは使えないことに注意。そのような記述がない場合は「php artisan route:cache」も実施のこと。

2回目以降のデプロイ時のコマンド #

当然ながら2回目以降は Clone ではなく Pull する。

git pull origin main

Laravel に関しては、初回デプロイ以外では以下コマンドは不要。特に「key:generate」や「migrate:fresh」は間違っても実施しないように。

# chmod -R 777 storage bootstrap/cache
# php artisan key:generate
# php artisan storage:link
# php artisan migrate:fresh

2回目以降のデプロイ時には以下のコマンドのみを実施する。

composer install --optimize-autoloader --no-dev
php artisan migrate
php artisan config:cache
php artisan view:cache

上記に加えて必要ならば「php artisan route:cache」する。

その他、ELB / EC2 関連で気をつけるべき点 #

実際には、EC2 の前段に ELB を配置、それに Certificate Manager で発行した SSL サーバ証明書を当てることで https 化して運用する構成が多い。

ELB / EC2 の設定における注意点 #

ELB と EC2 間を https 化する必要性はない。その意図を反映して、手順中に記載した Nginx の conf ファイルでも、80 番ポートのみを開放している。

全体の通信の流れは具体的には下記となる。

  • クライアント → (https : 443) → ELB → (http : 80) → EC2

上図に従って、ロードバランサーのリスナーは「https」で、ターゲットグループのプロトコルおよびヘルスチェックは「http」で作成するのが正解。

しかし、ここでのロードバランサーの設定とターゲットグループのプロトコル設定で間違いを犯し易いため注意すること。ターゲットグループのプロトコルを誤って https で作成している場合、通信を行った時に「502 Bad Gateway」などのエラーが出るので、そこでミスに気付きたい。

Laravel の設定における注意点 #

上記の構成で運用する場合、Laravel の設定も更新する必要がある。

上記の公式ドキュメントを参考に、「App\Http\Middleware\TrustProxies」のミドルウェアの設定を更新すること。更新後の例は以下。

<?php

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array|string|null
     */
    protected $proxies = '*';

    /**
     * The headers that should be used to detect proxies.
     *
     * @var int
     */
    protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
}

以上 #

お疲れさまでした!

参考記事 #