What's?
ApacheおよびPHP(PHP-FPM)のオフィシャルDockerイメージを使って、PHPの環境を作ってみようということで。
環境と前提
今回の環境。
Docker。
$ docker version
Client: Docker Engine - Community
Version: 20.10.11
API version: 1.41
Go version: go1.16.9
Git commit: dea9396
Built: Thu Nov 18 00:37:06 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.11
API version: 1.41 (minimum version 1.12)
Go version: go1.16.9
Git commit: 847da18
Built: Thu Nov 18 00:35:15 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.12
GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc:
Version: 1.0.2
GitCommit: v1.0.2-0-g52b36a2
docker-init:
Version: 0.19.0
GitCommit: de40ad0
ApacheとPHPのコンテナは、Docker Composeで立てることにします。
$ docker-compose version
Docker Compose version v2.1.1
利用するDockerイメージですが、それぞれ以下とします。
httpd:2.4.51
php:7.4.26-fpm
単にPHPを動かしたいだけなら、php:<version>-apache
を使えば済むようにも見えますが、今回はFPMを使うということでやってみます。
ApacheとPHP-FPM、2つのコンテナをDocker Composeで起動するという構成を目指します。
Apacheの設定ファイルを作成する
できる限り、オフィシャルのイメージそのままでいきたいのですが、Apacheに関しては設定ファイルを作成する必要があります。
こんなファイルを作成。
LoadModule proxy_module modules/mod_proxy.so
LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
AddType text/html .php
DirectoryIndex index.php
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
<LocationMatch \.(php|phar)$>
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/var/www/html%{reqenv:REQUEST_URI}"
SetHandler "proxy:fcgi://php-fpm:9000"
</LocationMatch>
mod_proxy
、mod_proxy_fcgi
は少なくともロードしておく必要があります。
ApacheからPHP-FPMへの転送は、別コンテナなのでTCPで行うようにしました。
<LocationMatch \.(php|phar)$>
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/var/www/html%{reqenv:SCRIPT_NAME}"
SetHandler "proxy:fcgi://php-fpm:9000"
</LocationMatch>
UNIXドメインソケットで構成してもよかったのですが、PHP-FPM側がTCPポート9000でリッスンしている状態で構成されているようだったので、こちらに合わせました。
php-fpm
というのは、転送先のコンテナ名です。
また、以下の部分もポイントで
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/var/www/html%{reqenv:SCRIPT_NAME}"
これがないと、以下のエラーにずっと悩まされることになります。
[proxy_fcgi:error] [pid 10:tid 140642638350080] [client 172.17.0.1:35954] AH01071: Got error 'Primary script unknown'
これは、ApacheのオフィシャルイメージとPHP-FPMのオフィシャルイメージでドキュメントルートに差異があり、これを合わせるためのものです。
- Apache -
/usr/local/apache2/htdocs
- PHP-FPM -
/var/www/html
Docker Composeを設定を作成する
PHP-FPM側には特に設定は要らないので、あとはdocker-compose.yml
を作成します。
最終的にできあがったdocker-compose.yml
は、こちら。
version: "3.9"
services:
apache:
image: httpd:2.4.51
ports:
- "80:80"
depends_on:
- php-fpm
volumes:
- ./apache2/conf/extra/proxy-php.conf:/usr/local/apache2/conf/extra/proxy-php.conf
networks:
php_network:
aliases:
- apache
entrypoint: >-
bash -c "
grep 'Include conf/extra/proxy-php.conf' /usr/local/apache2/conf/httpd.conf || echo 'Include conf/extra/proxy-php.conf' >> /usr/local/apache2/conf/httpd.conf
httpd-foreground
"
php-fpm:
image: php:7.4.26-fpm
volumes:
- ./app:/var/www/html
networks:
php_network:
aliases:
- php-fpm
networks:
php_network:
driver: bridge
Apache側のポイントですが
apache:
image: httpd:2.4.51
ports:
- "80:80"
depends_on:
- php-fpm
volumes:
- ./apache2/conf/extra/proxy-php.conf:/usr/local/apache2/conf/extra/proxy-php.conf
networks:
php_network:
aliases:
- apache
entrypoint: >-
bash -c "
grep 'Include conf/extra/proxy-php.conf' /usr/local/apache2/conf/httpd.conf || echo 'Include conf/extra/proxy-php.conf' >> /usr/local/apache2/conf/httpd.conf
httpd-foreground
"
先ほど作成した設定ファイルをvolumeとしてマウントしていることと
volumes:
- ./apache2/conf/extra/proxy-php.conf:/usr/local/apache2/conf/extra/proxy-php.conf
起動時に設定ファイルのInclude
を追加していることですね。
entrypoint: >-
bash -c "
grep 'Include conf/extra/proxy-php.conf' /usr/local/apache2/conf/httpd.conf || echo 'Include conf/extra/proxy-php.conf' >> /usr/local/apache2/conf/httpd.conf
httpd-foreground
"
/usr/local/apache2/conf/extra
にファイルを置いておけば読んでくれるかと思ったのですが、そうはいきませんでした…。
PHP-FPM側は、ソースコードを/var/www/html
にvolumeとしてマウントします。
php-fpm:
image: php:7.4.26-fpm
volumes:
- ./app:/var/www/html
networks:
php_network:
aliases:
- php-fpm
動作確認する
あとは、動作確認用のPHPファイルを作成して
<?php
phpinfo();
起動。
$ docker-compose up
http://localhost/index.php
にアクセスすると、PHPが動作していることが確認できます。