CentOS 6, Apache 2.2サーバーでPHP複数バージョンを使用する
はじめに
1つのサーバーOSで複数のWebサイトをホストしている場合、PHPの複数バージョンを使用したい(バージョンを混在させたい)、というケースがあります。
たとえば、
Webサイト1は、PHP 5.6が必要(PHP 7に非対応)
Webサイト2は、PHP 7.2が必要(PHP 5に非対応)
など。
このような場合、複数バージョンのPHPをインストールし、各バージョンごとのPHP-FPMを起動します。
そして、Apache 2.4であれば、Apacheの設定で SetHandler で mod_proxy_fcgi を使用して、ホスト名やURLパスなどの条件に応じて、各バージョンのPHP-FPMに紐づければOKです。
PHP 5.6のWebサイト向け。
<FilesMatch \.php$> SetHandler "proxy:fcgi://127.0.0.1:9056" </FilesMatch>
PHP 7.2のWebサイト向け。
<FilesMatch \.php$> SetHandler "proxy:fcgi://127.0.0.1:9072" </FilesMatch>
PHPの処理を、FastCGIによる外部プロセスとしてApacheから外出しすることで、複数のPHPを混在できるというわけです。
(参考)
・Yum で複数バージョンの PHP を共存させる – Qiita
https://qiita.com/bezeklik/items/860ba080bf4c664cd8e9
ところが、CentOS 6のリポジトリに含まれる Apache 2.2 の mod_proxy_fcgi は、SetHandlerに非対応なので、この方法は使えません。
また、以下のように ProxyPassMatch を使用する方法もありますが、、
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9072/var/www/html72/$1
この方法だと、「DirectoryIndex が効かない」「.htaccess でディレクトリごとの制御ができない」などの問題があります。
(参考)
・php-fpm での php 実行は SetHandler で! – あらかると
https://www.starlink.jp/php-fpm-sethandler/
この問題は、mod_proxy_fcgi の代わりに、mod_fastcgi を使用することで解決できます。
ここでは、Apache 2.2 + mod_fastcgi で、PHP複数バージョン環境を構築する手順を記載します。
前提条件と要件
- サーバーはCentOS 6で、Apache 2.2、CentOSリポジトリのPHP 5.3をインストール、mod_phpで設定、PHP 5.3のWebサイトを公開済み。
- PHP 5.3 に加えて、PHP 5.6, PHP 7.2 を追加する。
- PHP 5.3, PHP 5.6, PHP 7.2を使用するWebサイトのホスト名は次のとおり。
- PHP 5.3: http://php53.example.jp/
- PHP 5.6: http://php56.example.jp/
- PHP 7.2: http://php72.example.jp/
※HTTPS、サーバー証明書の設定はここでは割愛します。
構成イメージはこんな感じ。
設定手順
次の設定を行います。
1. リポジトリの追加
2. PHP 5.6のインストールとPHP-FPMの設定
3. PHP 7.2のインストールとPHP-FPMの設定
4. mod_fastcgiの設定
5. Apacheの設定
6. 動作確認
以下、rootユーザーもしくは、sudo権限で実行します。
1. リポジトリの追加
PHP 5.6, 7.2をインストールするため、Remiリポジトリ、EPELリポジトリを追加します。
まず、EPELリポジトリを追加します。
# yum install epel-release
続いて、Remiリポジトリを追加します。
# yum install http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
2. PHP 5.6のインストールとPHP-FPMの設定
2-1. PHP 5.6のインストール
Remiリポジトリより、PHP 5.6をインストールします。
PHP 5.6は、php56-php-xxx というパッケージ名で提供されています。
# yum --enablerepo=remi info php56-php-common -- Available Packages Name : php56-php-common Arch : x86_64 Version : 5.6.40 Release : 13.el6.remi Size : 693 k Repo : remi ... --
まず、php-gd, php-mcryptと依存関係のある libwebp, libmcrypt をインストールします。
# yum --enablerepo=epel install libwebp mcrypt
PHP 5.6をインストールします。
PHPモジュールは必要に応じて追加してください。
(僕はだいたいこんな感じです。)
PHP-FPMを使用するので、php56-php-fpm は必須です。
# yum --enablerepo=remi install php56 \ php56-php-devel \ php56-php-common \ php56-php-recode \ php56-php-mysql \ php56-php-gd \ php56-php-xml \ php56-php-tidy \ php56-php-mbstring \ php56-php-pdo \ php56-php-cli \ php56-php-pear \ php56-php-mcrypt \ php56-php-process \ php56-php-intl \ php56-php-fpm
PHP 5.6のバージョンを確認します。
# php56 --version PHP 5.6.40 (cli) (built: Aug 28 2019 15:35:39) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
PHP 5.6のConfigファイルの在り処を確認します。
# rpm -ql php56-php-common /opt/remi/php56/root/etc/php.d /opt/remi/php56/root/etc/php.d/20-bz2.ini /opt/remi/php56/root/etc/php.d/20-calendar.ini /opt/remi/php56/root/etc/php.d/20-ctype.ini /opt/remi/php56/root/etc/php.d/20-curl.ini /opt/remi/php56/root/etc/php.d/20-exif.ini /opt/remi/php56/root/etc/php.d/20-fileinfo.ini /opt/remi/php56/root/etc/php.d/20-ftp.ini /opt/remi/php56/root/etc/php.d/20-gettext.ini /opt/remi/php56/root/etc/php.d/20-iconv.ini /opt/remi/php56/root/etc/php.d/20-phar.ini /opt/remi/php56/root/etc/php.d/20-sockets.ini /opt/remi/php56/root/etc/php.d/20-tokenizer.ini /opt/remi/php56/root/etc/php.ini ...
※必要に応じて、php.ini を編集します(ここでは割愛します)。
2-2. PHP-FPMの設定
PHP-FPMのConfigファイルの在り処を確認します。
# rpm -ql php56-php-fpm /etc/logrotate.d/php56-php-fpm /etc/rc.d/init.d/php56-php-fpm /opt/remi/php56/root/etc/php-fpm.conf /opt/remi/php56/root/etc/php-fpm.d /opt/remi/php56/root/etc/php-fpm.d/www.conf /opt/remi/php56/root/etc/sysconfig/php-fpm ...
PHP-FPMのConfigを編集します。
以下、変更点のみ記載します。
ここでは、PHP-FPMのプロセスは、1~3で動的に増減するようにします。
listenポートとして、TCP/9056 を使用するようにするのがポイントです。
(本番運用では、適宜チューニングしてください。)
# vi /opt/remi/php56/root/etc/php-fpm.d/www.conf pm = ondemand pm.max_children = 3 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 2 pm.max_requests = 500 listen = 127.0.0.1:9056
PHP-FPMを起動します。
# /etc/init.d/php56-php-fpm start # ps aux | grep php-fpm root 1587 0.0 0.6 372796 7060 ? Ss 16:29 0:00 php-fpm: master process (/opt/remi/php56/root/etc/php-fpm.conf) apache 1588 0.0 0.6 372796 6140 ? S 16:29 0:00 php-fpm: pool www
3. PHP 7.2のインストールとPHP-FPMの設定
3-1. PHP 7.2のインストール
Remiリポジトリより、PHP 7.2をインストールします。
PHP 7.2は、php72-php-xxx というパッケージ名で提供されています。
# yum --enablerepo=remi info php72-php-common -- Available Packages Name : php72-php-common Arch : x86_64 Version : 7.2.22 Release : 1.el6.remi Size : 635 k Repo : remi ... --
PHP 7.2をインストールします。
PHPモジュールは必要に応じて追加してください。
PHP-FPMを使用するので、php72-php-fpm は必須です。
# yum --enablerepo=remi install php72 \ php72-php-devel \ php72-php-common \ php72-php-recode \ php72-php-mysqlnd \ php72-php-gd \ php72-php-xml \ php72-php-tidy \ php72-php-mbstring \ php72-php-pdo \ php72-php-cli \ php72-php-pear \ php72-php-mcrypt \ php72-php-process \ php72-php-opcache \ php72-php-intl \ php72-php-fpm
PHP 7.2のバージョンを確認します。
# php72 --version PHP 7.2.22 (cli) (built: Aug 28 2019 08:45:19) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.22, Copyright (c) 1999-2018, by Zend Technologies
PHP 7.2のConfigファイルの在り処を確認します。
# rpm -ql php72-php-common /etc/opt/remi/php72/php.d /etc/opt/remi/php72/php.d/20-bz2.ini /etc/opt/remi/php72/php.d/20-calendar.ini /etc/opt/remi/php72/php.d/20-ctype.ini /etc/opt/remi/php72/php.d/20-curl.ini /etc/opt/remi/php72/php.d/20-exif.ini /etc/opt/remi/php72/php.d/20-fileinfo.ini /etc/opt/remi/php72/php.d/20-ftp.ini /etc/opt/remi/php72/php.d/20-gettext.ini /etc/opt/remi/php72/php.d/20-iconv.ini /etc/opt/remi/php72/php.d/20-phar.ini /etc/opt/remi/php72/php.d/20-sockets.ini /etc/opt/remi/php72/php.d/20-tokenizer.ini /etc/opt/remi/php72/php.ini ...
※必要に応じて、php.ini を編集します(ここでは割愛します)。
3-2. PHP-FPMの設定
PHP-FPMのConfigファイルの在り処を確認します。
# rpm -ql php72-php-fpm /etc/logrotate.d/php72-php-fpm /etc/opt/remi/php72/php-fpm.conf /etc/opt/remi/php72/php-fpm.d /etc/opt/remi/php72/php-fpm.d/www.conf /etc/opt/remi/php72/sysconfig/php-fpm /etc/rc.d/init.d/php72-php-fpm ...
PHP-FPMのConfigを編集します。
以下、変更点のみ記載します。
ここでは、PHP-FPMのプロセスは、1~3で動的に増減するようにします。
listenポートとして、PHP 5.6のPHP-FPMが使用する TCP/9056 とは異なる、TCP/9072 を使用するようにするのがポイントです。
# vi /etc/opt/remi/php72/php-fpm.d/www.conf pm = ondemand pm.max_children = 3 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 2 pm.max_requests = 500 listen = 127.0.0.1:9056
PHP-FPMを起動します。
# /etc/init.d/php72-php-fpm start # ps aux | grep php-fpm root 1587 0.0 0.6 372796 7060 ? Ss 16:29 0:00 php-fpm: master process (/opt/remi/php56/root/etc/php-fpm.conf) apache 1588 0.0 0.6 372796 6140 ? S 16:29 0:00 php-fpm: pool www root 1761 0.0 0.8 506724 8524 ? Ss 17:32 0:00 php-fpm: master process (/etc/opt/remi/php72/php-fpm.conf) apache 1762 0.0 0.7 506724 7684 ? S 17:32 0:00 php-fpm: pool www
4. mod_fastcgiの設定
mod_fastcgi をインストール、設定します。
以下がとても参考になりました。
(参考)
・FastCGI+Apache+php インストールメモ(mod_fastcgi) – SOFTELメモ
https://www.softel.co.jp/blogs/tech/archives/5195
・複数バージョンのphpをapache+mod_fastcgiで扱う – OPENFORCE
https://www.open-force.info/177/show
・apache の FastCGI(mod_fastcgi) + PHP-FPM で phpを動かしてみる (CentOS,ScientificLinux編) – レンタルサーバー・自宅サーバー設定・構築のヒント
https://server-setting.info/centos/apache-mod_fastcgi-php-fpm.html
4-1. mod_fastcgiのインストール
mod_fastcgi 以前はRepoforgeリポジトリで提供されていましたが、Repoforgeリポジトリはなくなってしまいました。
パッケージ検索サイト pkgs.org で、mod_fastcgi を検索し、Repoforge (RPMforge) x86_64のRPMをダウンロード、インストールします。
※RPMファイルが信用できない場合は、公式サイトからソースをダウンロードして、ビルド、インストールするとよいでしょう。
# cd /usr/local/src/ # wget http://ftp.tu-chemnitz.de/pub/linux/dag/redhat/el6/en/x86_64/rpmforge/RPMS/mod_fastcgi-2.4.6-2.el6.rf.x86_64.rpm # yum install mod_fastcgi-2.4.6-2.el6.rf.x86_64.rpm
インストールされたファイルを確認します。
# rpm -ql mod_fastcgi /etc/httpd/conf.d/fastcgi.conf /usr/lib64/httpd/modules/mod_fastcgi.so ... /var/run/mod_fastcgi
4-2. mod_fastcgiの設定
/etc/httpd/conf.d/fastcgi.conf で、基本設定と、PHP-FPM を外部 FastCGIサーバーとして使用するための設定を行います。
FastCgiExternalServer を使用するので、FastCgiWrapper は Offにします。
FastCgiServer は使用しないので、FastCgiConfig はコメントアウトします。
# vi /etc/httpd/conf.d/fastcgi.conf User apache Group apache LoadModule fastcgi_module modules/mod_fastcgi.so # dir for IPC socket files FastCgiIpcDir /var/run/mod_fastcgi # wrap all fastcgi script calls in suexec #FastCgiWrapper On FastCgiWrapper Off # global FastCgiConfig can be overridden by FastCgiServer options in vhost config #FastCgiConfig -idle-timeout 20 -maxClassProcesses 1
以下を末尾に追記します。
ScriptAlias /fcgi-bin/ /var/www/fcgi-bin/ # PHP 5.6 FastCgiExternalServer /var/www/fcgi-bin/php-fpm56 -host 127.0.0.1:9056 -pass-header Authorization Action php-fastcgi56 /fcgi-bin/php-fpm56 # PHP 7.2 FastCgiExternalServer /var/www/fcgi-bin/php-fpm72 -host 127.0.0.1:9072 -pass-header Authorization Action php-fastcgi72 /fcgi-bin/php-fpm72
ScriptAliasで指定したディレクトリ /var/www/fcgi-bin が存在しないと動作しないので、作成します。
(/var/www/fcgi-bin/php-fpm56, /var/www/fcgi-bin/php-fpm72 は作成不要です。)
# mkdir /var/www/fcgi-bin
これで、Apache のVirtualHost Configなどで、
SetHandler php-fastcgi56
を指定すると、PHP 5.6用のPHP-FPM (127.0.0.0:9056) に、
SetHandler php-fastcgi72
を指定すると、PHP 7.2用のPHP-FPM (127.0.0.0:9072) に
接続するようになります。
5. Apacheの設定
5-1. PHP 5.6 http://php56.example.jp/ 用の設定
まず、httpd.conf で、NameVirtualHost を有効にします。
# vi /etc/httpd/conf/httpd.conf NameVirtualHost *:80
VirtualHost Configを作成します。
拡張子 .php に対して、「SetHandler php-fastcgi56」を設定することで、PHP 5.6用のPHP-FPMに接続させるのがポイントです。
# vi /etc/httpd/conf.d/vhost_php56.example.jp.conf <VirtualHost *:80> DocumentRoot /var/www/html56 ServerName php56.example.jp <FilesMatch ".+\.php$"> SetHandler php-fastcgi56 </FilesMatch> ErrorLog logs/php56.example.jp-error_log CustomLog logs/php56.example.jp-access_log combined </VirtualHost>
5-2. PHP 7.2 http://php72.example.jp/ 用の設定
VirtualHost Configを作成します。
拡張子 .php に対して、「SetHandler php-fastcgi72」を設定することで、PHP 7.2用のPHP-FPMに接続させるのがポイントです。
# vi /etc/httpd/conf.d/vhost_php72.example.jp.conf <VirtualHost *:80> DocumentRoot /var/www/html72 ServerName php72.example.jp <FilesMatch ".+\.php$"> SetHandler php-fastcgi72 </FilesMatch> ErrorLog logs/php72.example.jp-error_log CustomLog logs/php72.example.jp-access_log combined </VirtualHost>
5-3. Apacheに反映
Configの文法チェックを行い、問題なければ、Apacheを再起動します。
# /etc/init.d/httpd configtest # /etc/init.d/httpd restart
6. 動作確認
phpinfo()を実行するphpを設置してみます。
# vi /var/www/html/info.php <?php phpinfo(); ?> # mkdir /var/www/html56 # vi /var/www/html56/info.php <?php phpinfo(); ?> # mkdir /var/www/html72 # vi /var/www/html72/info.php <?php phpinfo(); ?>
PCのWebブラウザからアクセスして、PHPの情報を確認します。
「PHP Version」でPHPのバージョンが確認できます。
また、「Server API」で、PHP-FPM(FastCGI)を使用しているかどうかが確認できます。
http://php53.example.jp/info.php
にアクセス。
PHP Version 5.3.3 ... Server API: Apache 2.0 Handler
http://php56.example.jp/info.php
にアクセス。
PHP Version 5.6.40 ... Server API: FPM/FastCGI
http://php72.example.jp/info.php
にアクセス。
PHP Version 7.2.22 ... Server API: FPM/FastCGI
確認が終わったら、セキュリティ上好ましくないため、phpinfo() のファイルを削除します。
# rm /var/www/html/info.php \ /var/www/html56/info.php \ /var/www/html72/info.php
これで、PHP複数バージョンの環境ができました。
PHPバージョンを必要な分だけインストールして、PHP-FPMをlistenポートを変更して起動していけば、いくつでもPHPバージョンを増やせます。
補足
不具合
先日、この方法でPHP 5.3とPHP 7.2の複数バージョン設定を行った際、ページ遷移の際にURLパスが
http://php72.example.jp/fcgi-bin/php-fpm56/menu/
のように、fastcgi.conf の Action で定義したパスが含まれてしまい、遷移後のページが正しく表示されない現象が発生しました。
調査したところ、HTTPSからHTTP(またはその逆)に遷移する場合、このような不具合が発生することがわかりました。
いろいろ試しましたがうまく解決する方法がなく、結局、(本来はHTTPのままにしたかった)HTTPページを強制的にHTTPSにリダイレクトすることで、ページ表示が正しくなりました。
Webサイト内で、HTTPSページとHTTPページが混在するのは好ましくありませんし、レアケースかと思いますが、このような不具合がありました。
他にも、うまくいかないケースがあるかもしれません。
ひとつのVirtualHost内で複数のPHPバージョン
ひとつのVirtualHost内で、URLパスによってPHPバージョンを変更したい場合は、<Directory> もしくは .htaccess で、ディレクトリごとに制御するとよいでしょう。
デフォルトはPHP 5.3で、/php56 は PHP 5.6、/php72 は PHP 7.2 とする場合。
(2020.9.18追記)
php56, php72のディレクトリパスの指定が間違っていたので修正しました。
(2020.9.18追記ここまで)
# vi /etc/httpd/conf.d/vhost_php.example.jp.conf <VirtualHost *:80> DocumentRoot /var/www/html ServerName php.example.jp <Directory /var/www/html/php56> <FilesMatch ".+\.php$"> SetHandler php-fastcgi56 </FilesMatch> </Directory> <Directory /var/www/html/php72> <FilesMatch ".+\.php$"> SetHandler php-fastcgi72 </FilesMatch> </Directory> ...
↑mod_phpの設定(/etc/httpd/conf.d/php.conf)が効いているので、デフォルトはPHP 5.3となります。
デフォルトはPHP 7.2で、/php53 は PHP 5.3、/php56 は PHP 5.6 とする場合。
# vi /etc/httpd/conf.d/vhost_php.example.jp.conf <VirtualHost *:80> DocumentRoot /var/www/html ServerName php.example.jp <FilesMatch ".+\.php$"> SetHandler php-fastcgi72 </FilesMatch> <Directory /var/www/html/php53> <FilesMatch ".+\.php$"> SetHandler application/x-httpd-php </FilesMatch> </Directory> <Directory /var/www/html/php56> <FilesMatch ".+\.php$"> SetHandler php-fastcgi56 </FilesMatch> </Directory> ...
↑mod_phpの設定(/etc/httpd/conf.d/php.conf)が効いているので、「SetHandler application/x-httpd-php」で、PHP 5.3となります。
PHP 5.3もPHP-FPM化
今回記載した構築手順は、PHP 5.3のみ mod_php を使用し、PHP 5.6/7.2は mod_fastcgi + PHP-FPM という構成でした。
この構成は、サーバー全体のメモリ使用の効率がよくないと(僕は)思います。
PHPを処理したApacheの子プロセスは、メモリ使用量が増えた状態で次のリクエストを待ち受けることになります。
ですので、PHP 5.3も専用のPHP-FPMを起動して、PHPはすべて mod_fastcgi + PHP-FPM という構成にしてしまったほうがよいでしょう。
そうすれば、Apacheは静的処理、PHP-FPMは動的処理と役割分担がはっきりしますし、Apacheのメモリ使用量が少なくなります。
PHP-FPMを起動する分のメモリ使用量増がありますが、サーバー全体では、メモリ使用量が少なくなるでしょう。
構成イメージはこんな感じになります。
おわりに
CentOS 6, Apache 2.2 のサーバー環境で、PHP複数バージョンを使用するための設定手順をまとめました。
CentOS 6のサポートは、2020年11月末までですので、残り少ない期間ですが、サーバーのOSをCentOS 7または8にアップデートする前に、PHPのみバージョンアップして動作確認もしくは運用したい場合は、有効な方法だと思います。