概要
PHPを触るにあたりローカルでPHPを使って開発できる環境が欲しかったのでDocker Composeを使ってnginx + PHP-FPMで実行環境を構築しました。
PHPやPHP-FPM、Dockerの知識不足で構築に結構時間がかかってしまったので忘れないよう記事にします。
PHPのローカル開発環境としてMAMPやXAMPPなどがありますがワンクリックインストールで終わってしまっては面白くないのでDocker Composeを使用しました。
※Macのストレージを汚したくないと言う思惑もありました。
PHPに関してはズブの素人でProgateのPHPの学習コース1を先日、2時間ほどかけて基本構文を覚えたばかりです。
目次
参考サイト様
- 初心者用PHP入門 🔗
- nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する - Qiita 🔗
- ApacheとNginxについて比較 - Qiita 🔗
- Compose file versions and upgrading | Docker Documentation 🔗
- Compose file version 3 reference | Docker Documentation 🔗
- nginx docker container: 502 bad gateway response - Stack Overflow 🔗
- Networking in Compose #links | Docker Documentation 🔗
- docker-compose depends_onとlinksの違い - Qiita 🔗
環境
- Mac OS X Mojave 10.14.4
- Visual Studio Code Version: 1.33.1
$ docker -v
Docker version 18.09.2, build 6247962
$ docker-compose -v
docker-compose version 1.23.2, build 1110ad01
成果物
PHP動作環境のお勉強
PHPはスクリプト言語ではあるがサーバサイドスクリプトであるため、
JavaScript(クライアントサイドスクリプト)とは違いブラウザで処理してくれません。
PHPを実行するサーバを別途用意する必要があります。
ココらへんの触りの部分は下記のサイトが参考になりました。
環境を構築する際にサーバサイドで処理を実行してくれるWebサーバにApacheではなくNignxを選択したため、追加の知識としてPHP-FPMなどのお勉強をする必要がありました。
PHP-FPMについては下記の記事が大変丁寧でわかりやすかったです。
ズブの素人なのでそこまで詳しく追うわけではないけどザックリイメージの話をすると
FPMはCGIの上位互換であるFastCGIを実装したものでnginxではFastCGIを通してPHPを実行するのでFPMが必要となります。
WebサーバとしてApacheを使用するのであればPHPのモジュール版を使用するためPHP-FPMは不要となります。 ※そのうちもっと詳しくなるために調べようと思います。
Docker ComposeでPHP実行環境の構築
今回は、ローカルでphpinfo
を表示することを最終目標に実行環境を構築します。
構築環境の構成
- Webサーバ
- nginxを使用したWebサーバ、FastCGIサーバへのプロキシとなる。
- PHP-FPMサーバ
- PHPの実行環境、FastCGIサーバ
Webサーバ(nginx)をプロキシとしてPHP-FPM(FastCGI)サーバでPHPを実行するイメージです。
※間違ってたらコメントください。
ディレクトリ構成
サンプルプロジェクトのディレクトリ構成は以下の通り。
docker-configs
に各コンテナで使用する設定ファイルやビルド用のDockerfileを突っ込む想定で作成しました。
今回は、公式イメージを使って環境を構築するためビルド用のDockerfileは作成しません。
src
にはPHPファイルを配置します。
$ tree
.
├── docker-compose.yml
├── docker-configs
│ └── nginx
│ └── nginx.conf
└── src
└── index.php
docker-compose.yml
の作成
Docker Composeを使ってコンテナ群をまとめて管理します。
そのための設定ファイル(手順書)がdocker-compose.yml
です。
docker-compose.yml
version: "3.7"
services:
# セクション名については任意の名前で構わない。
web:
# Dockerイメージを指定
image: nginx:latest
ports:
# プロキシサーバのポートを指定(ホスト側:コンテナ側)
- "8080:80"
volumes:
# nginxのconfigファイルをマウントしdefault.confへ上書き
- ./docker-configs/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
php:
# Dockerイメージを指定、PHPバージョンは7.3
image: php:7-fpm
# FastCGIサーバのデフォルトポートを使用するためports指定なし
volumes:
# 実行対象のPHPファイルをマウント
- ./src/:/var/phpapp/
docker-compose.yml
の記述バージョン
ファイル先頭で指定しているversion
により使用できるDockerのバージョンが異なります。
将来的にバージョン1
は非推奨となるっぽいのでバージョン2
以上を使うほうが良さげ。
各対応バージョンは下記のリンクを参照のこと。
今回は公式ドキュメントのサンプルを使用したので最新のバージョン3.7
となっています。
services
セクション
各コンテナの設定を記述します。
今回はWebサーバとなるweb
とFastCGIサーバとなるphp
コンテナを定義しました。
各セクションのリファレンスは下記の公式ドキュメントを参照のこと。
image
セクション
Dockerイメージについては公式のイメージを使用し、nginxについては特にバージョンを考えていないのでlatest
を指定しています。
image: nginx:latest
PHP-FPMのイメージについてはタグで必要なイメージを指定します。
PHPのバージョンは7.3
となります。
image: php:7-fpm
ports
セクション
ports
セクションではnginxのプロキシサーバのポートを指定します。
8080:80
がホスト側ポート:コンテナ内ポート
と言う具合です。
ports:
- "8080:80"
また、ports
セクションについては"(ダブルクオート)
を使用して明示的に文字列とするよう公式ドキュメントに記載があります。
※FastCGIサーバではデフォルトポートの9000番
を使用するためports
の指定は行いません。
volumes
セクション
そして、volumes
でディレクトリやファイルをマウントします。
こうすることでホストのストレージにあるファイルとコンテナ内のファイルを同期できます。
※共有ディスク化と言ったほうが語弊少なめ?
nginxの場合はconfigファイルを作成しdefault.conf
へ上書きします。
configファイルのファイル名についてはマウント対象であるdefault.conf
への上書きであるため任意の名前で構いません。
volumes:
- ./docker-configs/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
FastCGIサーバの場合は実行したいPHPファイルがあるディレクトリをマウントします。
volumes:
- ./src/:/var/phpapp/
nginxのconfigファイル作成
nginxのconfig(設定)ファイルを作成します。
全然詳しくないのでデフォルトの設定ファイル(default.conf
)に手を加える形で作成します。
※Gitのcommit差分でわかりやすいようにすればよかったんですがそうしてなかったのでいきなり完成品です。
変更した部分については変更前のものをコメントの形式で記載しています。 また、configファイルを作成するにあたり下記の記事が大変役に立ちました。
-
参考:nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する #基本的な設定 - Qiita 🔗
-
docker-configs/nginx/nginx.conf
server {
listen 80;
server_name localhost;
# root /usr/share/nginx/html;
# $document_rootの値となる
root /var/phpapp;
# index index.html index.htm;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
# root html;
# docker-composeでホストが自動でリンク(設定)されるためサービス名が指定可能 -> php
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass php:9000;
fastcgi_index index.php;
# FastCGIに渡すパラメータを修正
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
ココらへんはノリでこんな感じだろと乗り切ったので解説できるほど理解できてないです。 ハマったポイントだけ記載しておきます。
fastcgi_pass
について
fastcgi_pass
はデフォルトで127.0.0.1:9000
を指定しています。
そのままコンテナを起動するとnginxが502(BadGateway)
を返してしまいます。
原因は、dockerコンテナの127.0.0.1
がlocalhost
(コンテナ自体)となるためです。
これを回避するために、PHP-FPMを別立てしている場合はPHP-FPMのコンテナを指定してやる必要があります。
ここで少しハマりました。下記のStackOverflowにすべて書いてあった感じです。
Docker Composeでコンテナをまとめて起動する場合はdocker-compose.yml
で定義されたコンテナすべてのホストが自動で設定されるのでサービス名で指定可能です。
(ここで述べているサービス名はdocker-compose.yml
で設定したweb
やphp
のこと)
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass php:9000;
- 参考:Compose file version 3 reference #links | Docker Documentation 🔗
- 参考:Networking in Compose #links | Docker Documentation 🔗
- 参考:docker-compose depends_onとlinksの違い - Qiita 🔗
index.php
の作成
phpinfo
を表示することが目標なのでphpinfo
を表示するためのページを作成します。
src/index.php
<?php
echo phpinfo();
?>
PHP実行環境の起動
ターミナルから先程設定したコンテナを起動します。
$ pwd
/php-sample
$ docker-compose up
# 初回は時間がかかる。最終的にこんな感じのログが出るはず。
Creating network "php-sample_default" with the default driver
Creating php-sample_web_1 ... done
Creating php-sample_php_1 ... done
Attaching to php-sample_web_1, php-sample_php_1
php_1 | [30-Apr-2019 15:40:17] NOTICE: fpm is running, pid 1
php_1 | [30-Apr-2019 15:40:17] NOTICE: ready to handle connections
初回はイメージのダウンロードなどで時間がかかりますがいい感じにログが出てればOK
ブラウザからhttp://localhost:8080
にアクセスすると下記の画面が表示されます。
docker-composeコマンドについて(補足)
設定を変更して反映させたいときはdown
を使ってコンテナごと削除すると良さげ
# バックグラウンド実行
$ docker-compose up -d
# コンテナの停止
$ docker-compose stop
# コンテナの停止&削除
$ docker-compose down
雑感
PHPの環境構築にめっちゃ時間取られちゃいました。
わからないことだらけなので隙間を埋めるように勉強続けたいですね。