lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

Docker Composeを使ってnginxとPHP-FPMでPHPの実行環境を構築する

概要

PHPを触るにあたりローカルでPHPを使って開発できる環境が欲しかったのでDocker Composeを使ってnginx + PHP-FPMで実行環境を構築しました。
PHPPHP-FPM、Dockerの知識不足で構築に結構時間がかかってしまったので忘れないよう記事にします。

PHPのローカル開発環境としてMAMPやXAMPPなどがありますがワンクリックインストールで終わってしまっては面白くないのでDocker Composeを使用しました。
Macのストレージを汚したくないと言う思惑もありました。

PHPに関してはズブの素人でProgateのPHPの学習コース1を先日、2時間ほどかけて基本構文を覚えたばかりです。

目次

参考サイト様

環境

$ 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を表示することを最終目標に実行環境を構築します。

f:id:HM_Atlas:20190501022139p:plain

構築環境の構成

  • Webサーバ
    • nginxを使用したWebサーバ、FastCGIサーバへのプロキシとなる。
  • PHP-FPMサーバ

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サーバとなるwebFastCGIサーバとなる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ファイルを作成するにあたり下記の記事が大変役に立ちました。

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.1localhost(コンテナ自体)となるためです。

これを回避するために、PHP-FPMを別立てしている場合はPHP-FPMのコンテナを指定してやる必要があります。

ここで少しハマりました。下記のStackOverflowにすべて書いてあった感じです。

Docker Composeでコンテナをまとめて起動する場合はdocker-compose.ymlで定義されたコンテナすべてのホストが自動で設定されるのでサービス名で指定可能です。
(ここで述べているサービス名はdocker-compose.ymlで設定したwebphpのこと)

# fastcgi_pass   127.0.0.1:9000;
fastcgi_pass   php:9000;

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にアクセスすると下記の画面が表示されます。

f:id:HM_Atlas:20190501022139p:plain

docker-composeコマンドについて(補足)

設定を変更して反映させたいときはdownを使ってコンテナごと削除すると良さげ

# バックグラウンド実行
$ docker-compose up -d
# コンテナの停止
$ docker-compose stop
# コンテナの停止&削除
$ docker-compose down

雑感

PHPの環境構築にめっちゃ時間取られちゃいました。
わからないことだらけなので隙間を埋めるように勉強続けたいですね。