はじめに
AWS EC2サーバーのPHPとLaravelを最新バージョンに、アップデートする方法についてまとめました。
環境
現環境
- Amazon Linux 2
- PHP 7.2.8
- Laravel 5.7.9
- nginx 1.12.2
- composer 1.10.15 (なくても可)
アップデート後
- Amazon Linux 2
- PHP 8.0.16
- Laravel 9.5.1
- nginx 1.20.0
- composer 2.2.7
PHPバージョンアップ
PHPバージョンは7.2なので、PHP8にバージョンアップします。
PHPをバージョンアップする前に、/etc/php.ini
ファイルをローカルにコピーしておいてください。
バージョンアップすると、/etc/php.ini
ファイルは、デフォルトに書き換えられます。
$ php -v
PHP 7.2.8
PHPのバージョンを変える場合、PHPのパッケージをすべてアンインストールしてから PHP8を有効化する流れになります。
// パッケージアップデート
$ sudo yum update -y
// PHPのパッケージをすべてアンインストール
$ sudo yum -y remove php-*
// amazon-linux-extrasをアップデート
$ sudo yum update -y amazon-linux-extras
// amazon-linux-extrasで使用中のパッケージと使えるパッケージを確認
$ amazon-linux-extras
// php7.2を無効化
$ sudo amazon-linux-extras disable php7.2
// PHP8.0を有効化
$ sudo amazon-linux-extras enable php8.0
// PHP8.0をインストール
sudo amazon-linux-extras install -y php8.0
// インストールするパッケージの案内があったので、表示されたコマンドを実行
$ sudo yum clean metadata && sudo yum install -y php-cli php-pdo php-fpm php-mysqlnd
// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service
// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
$ php -v
PHP 8.0.16
PHP8にバージョンアップできました。
phpモジュール
phpのバージョンアップ後に、phpモジュールがなくなる場合がありますので、バージョンアップ前にモジュールを確認しておきます。
確認する内容として、rpm -qa|grep php
とphp -m
の2つがあります。
今回は、例としてバージョンアップ後にphp-mbstring
が無くなったと仮定し、再度インストールする方法について記述します。
Laravelだとphp-mbstring
は必須かと思います。
$ rpm -qa|grep php
php-mbstring-7.2.8-3.amzn2.0.2.x86_64
などなど
$ php -m
[PHP Modules]
mbstring
$ rpm -qa|grep php
//php-mbstringなし
$ php -m
[PHP Modules]
//php-mbstringなし
以下のコマンドでphp-mbstring
をインストールします。
$ sudo yum install -y php-mbstring
$ rpm -qa|grep php
php-mbstring-8.0.16-1.amzn2.x86_64.rpm
$ php -m
[PHP Modules]
mbstring
//再起動を忘れずに
$ sudo nginx -s reload
$ sudo systemctl restart php-fpm
php-mbstring
をインストールできました。
php.ini修正
以下の修正をしました。
$ sudo vim /etc/php.ini
- expose_php = On
+ expose_php = Off
# 下記は、お好きに
max_execution_time = 30
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = -1
error_reporting = E_ALL
display_errors = off
display_startup_errors = off
log_errors = on
default_charset = UTF-8
date.timezone = Asia/Tokyo
nginxバージョンアップ
PHPと同様に、パッケージをすべてアンインストールしてから nginxの最新バージョンを有効化する流れになります。
nginxをバージョンアップする前に、/etc/nginx/nginx.conf
ファイルをローカルにコピーしておいてください。
バージョンアップすると、/etc/nginx/nginx.conf
ファイルがデフォルトに書き換えられます。
$ nginx -v
nginx version: nginx/1.12.2
$ rpm -qa|grep nginx
nginx-all-modules-1.12.2-2.amzn2.0.2.noarch
nginx-mod-mail-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-stream-1.12.2-2.amzn2.0.2.x86_64
nginx-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-xslt-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-perl-1.12.2-2.amzn2.0.2.x86_64
nginx-filesystem-1.12.2-2.amzn2.0.2.noarch
nginx-mod-http-image-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-geoip-1.12.2-2.amzn2.0.2.x86_64
$ sudo yum -y remove nginx-mod*
$ sudo amazon-linux-extras disable nginx1.12
$ sudo amazon-linux-extras install nginx1
$ rpm -qa|grep nginx
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch
$ rpm -qa|grep nginx
nginx-filesystem-1.22.0-1.amzn2.0.1.noarch
nginx-core-1.22.0-1.amzn2.0.1.x86_64
nginx-1.22.0-1.amzn2.0.1.x86_64
$ nginx -v
nginx version: nginx/1.20.0
// nginx.confファイルを修正します。
$ sudo vim /etc/nginx/nginx.conf
//設定ファイルのチェック
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
モジュールが必要であれば以下のコマンドでインストールも可能です。
ただ、私の場合エラーがでました。
// nginx-modをインストール
$ sudo yum -y install nginx-mod*
$ rpm -qa|grep nginx
nginx-mod-http-xslt-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-geoip-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-mail-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-stream-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch
nginx-mod-http-image-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-perl-1.20.0-2.amzn2.0.4.x86_64
$ sudo nginx -t
nginx: [emerg] module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so" version 1020000 instead of 1022000 in /usr/share/nginx/modules/mod-http-geoip.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed
対処法がこちらです。よって、上記のモジュールはインストールしませんでした。
nginx.confの設定ファイル
nginx.confファイルの修正は、特に、server内がデフォルトになっているため、元に戻す必要があります。
下記のserver_name
,root
,location(3行)
は、必ず修正してください。
server {
listen 80;
listen [::]:80;
server_name example.com;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
参考として、Laravelのドキュメントにnginxのnginx.confの一例が記載されています。
コピーする必要はありません。
ちなみに、私の場合、nginx.confを最小限の記述で以下の設定になりました。
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
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;
server_name example.com;
root /var/www/html/public;
include /etc/nginx/default.d/*.conf;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
}
nginx.confでは、デフォルトでconf設定ファイルに関するinclude
を以下の2箇所使用されておりましたので、そちらもファイルも記載しておきます。
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/default.d/*.conf;
# PHP-FPM FastCGI server
# network or unix domain socket configuration
upstream php-fpm {
server unix:/run/php-fpm/www.sock;
}
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;
location ~ \.(php|phar)(/.*)?$ {
fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;
fastcgi_intercept_errors on;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php-fpm;
}
index index.php index.html index.htm;
などは、/etc/nginx/default.d/php.conf
に記載されているため、nginx.confに記載する必要がないことが分かりますね。
php-fpmの設定ファイル修正
php-fpmの設定ファイルもデフォルトに上書きされるため、修正します。
$ sudo vim /etc/php-fpm.d/www.conf
- user = apache
- group = apache
- ;listen.owner = nobody
- ;listen.group = nobody
- ;listen.mode = 0660
+ user = nginx
+ group = nginx
+ listen.owner = nginx
+ listen.group = nginx
+ listen.mode = 0660
再起動
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
composerバージョンアップ
composerをインストールしていない場合
こちらの記事を参考に最新版をインストールしましょう
$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37
composerがインストール済みの場合
// 現在のバージョン
$ composer -V
Composer version 2.1.9
// パーミッションエラーでバージョンアップデートできない
$ composer self-update
Upgrading to version 2.2.7 (stable channel).
[Composer\Downloader\FilesystemException]
Filesystem exception:
Composer update failed: "/usr/local/bin/composer" could not be written.
rename(/home/ec2-user/.cache/composer/composer-temp.phar,/usr/local/bin/composer): Permission denied
$ ls -la /usr/local/bin
-rwxr-xr-x 1 ec2-user ec2-user 2268732 10月 12 18:07 /usr/local/bin
// パーミッションを変更
$ sudo chmod 0777 /usr/local/bin
$ composer self-update
Upgrading to version 2.2.7 (stable channel).
Use composer self-update --rollback to return to version 2.1.9
$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37
// パーミッションを元に戻す
$ sudo chmod 0755 /usr/local/bin/
Laravelのバージョンアップ
Laravelは5系から9系にバージョンアップします。
まず、依存パッケージのアップデートが必要です。
今回、5系から9系にアップデートするため、composer.jsonファイルを修正します。
$ php artisan --version
Laravel Framework 5.7.9
$ vim composer.json
Laravelのドキュメントに、必要なアップデート情報が記載されていました。
7系、8系、9系を確認すると、以下のように、アップデートする必要があります。
下記の中で、元々パッケージが入っていないものは、入れる必要がありません。
"php": "^8.0"
"laravel/framework": "^9.0"
"nunomaduro/collision": "^6.1"
"guzzlehttp/guzzle": "^7.0.1"
"laravel/ui": "^3.0"
"phpunit/phpunit": "^9.0"
"laravel/tinker": "^2.0"
また、facade/ignition
がcomposer.jsonにある場合、下記に書き換える
- "facade/ignition"
+ "spatie/laravel-ignition": "^1.0"
fideloper/proxy
がある場合、Laravel9系では使用できないため、削除しましょう。
- "fideloper/proxy"
また、composerにphpのバージョンを伝えておくと、合わせてくれるため、以下のコマンドを実行します。
ちなみに、composer
はlaravelプロジェクトのルートディレクトリ
で実行してください。(appディレクトリがあるところ)
$ composer config platform.php 8.0.16
composer.json に以下が追記されました。
"config": {
"platform": {
"php": "8.0.16"
},
では、composer updateし、パッケージをインストールしましょう。
エラー対応1
$ composer update
Problem 1
- phpunit/phpunit[9.3.0, ..., 9.5.x-dev] require ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
- Root composer.json requires phpunit/phpunit ^9.3 -> satisfiable by phpunit/phpunit[9.3.0, ..., 9.5.x-dev].
どうやら、ext-dom
が必要なようです。
$ sudo yum -y install php-xml
$ composer update
無事インストールできました。バージョンを確認してみましょう。
エラー対応2
$ php artisan -V
PHP Fatal error: Declaration of App\Exceptions\Handler::report(Exception $exception) must be compatible with Illuminate\Foundation\Exceptions\Handler::report(Throwable $e) in /usr/share/nginx/html/user_html/app/Exceptions/Handler.php on line 35
app/Exceptions/Handler.php
の Exception の処理が 6.x から 7.x で変更されているため、修正が必要なようです。
$ vim app/Exceptions/Handler.php
修正
namespace App\Exceptions;
- use Exception;
+ use Throwable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
...
- public function report(Exception $exception)
+ public function report(Throwable $throwable)
{
- parent::report($exception);
+ parent::report($throwable);
}
...
- public function render($request, Exception $exception)
+ public function render($request, Throwable $throwable)
{
- return parent::render($request, $exception);
+ return parent::render($request, $throwable);
}
エラー対応3
$ php artisan -V
In cache.php line 91:
Call to undefined function str_slug()
Laravel6系から、ヘルパー関数がフレームワークから削除されたため、設定ファイルでエラーが発生しているようです。
laravel/helpersパッケージを追加すると、今までどおり利用できるので、追加しましょう。
$ composer require laravel/helpers
エラー対応4
以下のエラーが出ました。
$ php artisan --version
Error
Undefined constant Illuminate\Http\Request::HEADER_X_FORWARDED_ALL
at vendor/fideloper/proxy/config/trustedproxy.php:48
44▕ * - 'HEADER_X_FORWARDED_AWS_ELB' (If you are using AWS Elastic Load Balancer)
45▕ *
46▕ * @link https://symfony.com/doc/current/deployment/proxies.html
47▕ */
➜ 48▕ 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
49▕
50▕ ];
51▕
もしくは、laravelのアプリケーションの動作確認時、strage/logs/laravel.log
ファイルで以下のエラーが出る場合があります。
原因としては、アプリケーションの「信頼できるプロキシ」ミドルウェアを更新する必要があるためです。
下記参考記事
local.ERROR: Class "Fideloper\Proxy\TrustProxies" not found
{"exception":"[object] (Error(code: 0)
: Class \"Fideloper\\Proxy\\TrustProxies\" not found at
/usr/share/nginx/html/xxxxx/app/Http/Middleware/TrustProxies.php:8)
[stacktrace]
ファイルを修正します。
$ vim app/Http/Middleware/TrustProxies.php
修正
- use Fideloper\Proxy\TrustProxies as Middleware;
+ use Illuminate\Http\Middleware\TrustProxies as Middleware;
- protected $headers = Request::HEADER_X_FORWARDED_ALL;
+ 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;
念の為、fideloper/proxy
の依存関係をアプリケーションから削除するコマンドを実行しておきます。
$ composer remove fideloper/proxy
再度、Laravelのバージョンを確認しましょう。
$ php artisan --version
Laravel Framework 9.5.1
Laravel9にバージョンアップできました!
エラー対応5
ちなみに、以下のバージョンになった場合、composer.jsonを以下のように修正しましょう。
$ php artisan --version
Laravel Framework 9.x-dev
- "minimum-stability": "dev"
+ "minimum-stability": “stable”
- "prefer-stable": true
$ composer update
$ php artisan --version
Laravel Framework 9.5.1
バージョンアップできました!
エラー対応6
login機能のあるLaravelですと、storage/logs/laravel.logで以下のエラーが出力されました。
staging.ERROR: Trait "Illuminate\Foundation\Auth\AuthenticatesUsers" not found
{"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0):
Trait \"Illuminate\\Foundation\\Auth\\AuthenticatesUsers\" not found
at /var/www/html/app/Http/Controllers/Admin/Auth/LoginController.php:9)
laravel/uiをインストールするとエラーが解消されます。
$ composer require laravel/ui
エラー対応7
storage/logs/laravel.logで以下のエラーが出力されました。
In aws.php line 28:
Class "Aws\Laravel\AwsServiceProvider" not found
Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1
AWS-SDKをインストールするとよいです。
$ composer require aws/aws-sdk-php-laravel
Amazon ElastiCache の Redisを使用している場合
バージョンをあげることで、以下のエラーが出ました。
local.ERROR: Class "RedisCluster" not found {"exception":"[object]
(Error(code: 0): Class \"RedisCluster\" not found at
PHP8では、pecl
でredis
をインストールする必要があります。
ちなみに、yumだとインストールできませんでした。
$ sudo yum install php-pecl-redis
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core | 3.7 kB 00:00:00
amzn2extra-docker | 3.0 kB 00:00:00
amzn2extra-nginx1 | 3.0 kB 00:00:00
amzn2extra-php8.0 | 3.0 kB 00:00:00
パッケージ php-pecl-redis は利用できません。
エラー: 何もしません
// peclでインストールしますので、pearをインストールします
$ sudo yum install -y php-pear
// phpredisをインストールすると、ビルドエラーが起きるので、その前にphp-develとgccをインストールします
$ sudo yum install -y gcc
$ sudo yum install -y php-devel
// php.iniに追加
$ sudo su
# echo "extension=redis.so" > /etc/php.d/redis.ini
# exit
// peclでphpredisをインストールします。3つ聞かれますが、デフォルトでよいので、Enterを押しましょう。
$ sudo pecl install redis
enable igbinary serializer support? [no] :
enable lzf compression support? [no] :
enable zstd compression support? [no] :
$ sudo pecl list | grep redis
redis 5.3.7 stable
// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service
// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
動作確認時のエラー対応方法
上記の対応後も、動作がうまく行かない場合、下記の観点でエラー対応します。
- logの確認
- 設定ファイルの確認
- キャッシュクリア
- ファイルとディレクトリの権限
log確認コマンド
$ sudo tail -100 storage/logs/laravel.log
$ sudo tail -100 /var/log/php-fpm/www-error.log
// nginxの場合
$ sudo tail -100 /var/log/nginx/access.log
$ sudo tail -100 /var/log/nginx/error.log
// apacheの場合
$ sudo tail -100 /var/log/apache2/access.log
$ sudo tail -100 /var/log/apache2/error.log
もしくは
$ sudo tail -100 /var/log/httpd/access.log
$ sudo tail -100 /var/log/httpd/error.log
設定ファイルの確認
また、エラー原因となりやすい設定ファイルを確認・修正しましょう。
$ sudo vim .env
$ sudo vim /etc/nginx/nginx.conf
$ sudo vim /etc/php.ini
$ sudo vim /etc/php-fpm.d/www.conf
// 修正後は、webサーバーを再起動します。
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
キャッシュクリア
キャッシュされていることが原因で、エラーのままになることがあります。
$ php artisan cache:clear
$ php artisan config:clear
$ php artisan route:clear
$ php artisan view:clear
キャッシュクリアエラー
php artisan cache:clear
で以下のエラーが起きましたので、対応します。
エラー原因は、storage/framework/cacheディレクトリ以下にdataディレクトリが存在しないためですので、作成するだけです。
$ php artisan cache:clear
Failed to clear cache. Make sure you have the appropriate permissions.
$ sudo mkdir storage/framework/cache/data
$ touch storage/framework/cache/data/.gitkeep
$ sudo vim storage/framework/cache/.gitignore
.gitignoreにdata
は、反映するよう設定します。
/*
!.gitignore
!data
$ php artisan cache:clear
Application cache cleared!
キャッシュクリアできました。
ファイルとディレクトリの権限
Laravelの権限は、laravelのプロジェクトディレクトリに移動し、基本的に以下でよいです。
$ sudo chown -R nginx:nginx ./
$ sudo find ./ -type d -exec chmod 755 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache
ただし、EC2にファイルをアップロードするため、SFTP接続する場合、SSH接続時のユーザーに権限を持たせる必要があるたえ、以下の権限の方がよいです。
ユーザー名がec2-user
と仮定します。
$ sudo chown -R nginx:ec2-user ./
$ sudo find ./ -type d -exec chmod 775 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache
Laravel9からLaravel8系にバージョンを下げる
Laravel9だと修正箇所が多いため、Laravel8系にしたい場合もあるかと思います。
composer.json
を修正し、composer update
するだけです。
"laravel/framework": "^9.0" → "laravel/framework": "8.83.5"
"nunomaduro/collision": "^6.1" → "nunomaduro/collision": "^5.0"
$ composer update
$ php artisan --version
Laravel Framework 8.83.5
参考記事