Docker 公式の PHP イメージを使って Web サーバに相当するコンテナを作ってみる。今回のコンテナ例では立ち上げると phpinfo() を出力する PHP Web サーバを提供することとする。
また -v (--volume) オプションを使って、ローカルディスクの領域を Web サーバのドキュメントルートとしてマウントした際の挙動もあわせて確認する。
なお以下の例で実行している docker コマンドは、docker-machine で作られたホストに対して行っており、事前に docker-machine env
による環境変数が設定済みの状態。
Apache + PHP
コンテナイメージの準備
まず PHP の phpinfo() を出力するファイルを用意。
<?php
phpinfo();
続けて image ビルドのための Dockerfile を用意。ここでは、 Apache モジュールが同梱された PHP コンテナイメージをベースとして使う。
あわせて、先ほどの PHP ファイルをコンテナイメージに同梱するよう COPY
を使ってローカルファイルをコンテナに含めるようにする。コピー先は、ベースとなるコンテナが提供している仕様に基づくディレクトリとする。すなわち今回利用しているベースコンテナの php:apache の Apache がドキュメントルートとして利用しているディレクトリで、ここでは /var/www/html
となっている。
FROM php:apache
COPY ./public/info.php /var/www/html/
docker build
コマンドを使って、新たな自前 Docker イメージを作成する。
Dockerfile で定義した利用コンテナイメージのダウンロードが行われ、それを基にして新規イメージが作られる。
$ docker build -t sandbox-phpinfo-apache .
docker images
コマンドを実行すると、先ほど作った新規イメージが利用可能な状態であることがわかる。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
sandbox-phpinfo-apache latest 5cfc1b74c92a 42 seconds ago 481 MB
php 5.6-apache 385019d6807e 12 days ago 481 MB
docker run
コマンドでこの自前 Docker イメージからコンテナを実行する。
-p オプションはポートフォワード設定で、Docker ホストへのアクセスに対してコンテナへ流す設定を行っている。
$ docker run --name phpinfo -p 80:80 -d sandbox-phpinfo-apache
fe055eccf5d24cc1fa5cec7940a6e619480dc6b091e0b83a8f0217007a795de6
動作確認
起動した Apache + PHP コンテナイメージに対してアクセスしてみる。
まずは Docker ホストの IP アドレスを docker-machine ip
コマンドでチェック。
$ docker-machine ip dev
192.168.99.100
得られたアドレスを使って Docker ホストへブラウザでルートアクセスすると、phpinfo() が表示される。
ローカルディレクトリをマウントして Web サーバを動かす
続けて、ローカルの public ディレクトリを先ほどのコンテナの Apache ドキュメントルートとしてマウントして動かしてみる。
ローカルには先ほどの phpinfo() 出力プログラムとは違う内容のものを用意。
<?php
echo "Hello, world: ", time();
先ほどのコンテナを一旦止めて、-v オプションで public ディレクトリをドキュメントルートへマウントする。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fe055eccf5d2 sandbox-phpinfo-apache "apache2-foreground" 7 minutes ago Up 7 minutes 0.0.0.0:80->80/tcp phpinfo
$ docker stop phpinfo
phpinfo
$ docker run --name phpinfo2 -v /path/to/sandbox-docker-phpinfo-apache/public:/var/www/html -p 80:80 -d sandbox-phpinfo-apache
40b99a767cbc2fbddb90d22fdc9e70296401cbce625c6133c355b455bbb2f0c7
再びブラウザでルートアクセスすると、今度は phpinfo() ではなく、public/index.php
に書かれた Hello, world プログラムの結果が表示される。また、/info.php にアクセスすると phpinfo() が表示される。以上より、マウントした public ディレクトリがコンテナ内 Apache のドキュメントルートになって稼働していることがわかる。
Nginx + PHP-FPM
続いてもう1つ PHP サーバを動かすスタイルとしてよく見られる Nginx と PHP-FPM を組み合わせたサーバを Docker で作ってみる。ここでは、Nginx コンテナと PHP-FPM コンテナの2つを用意して、Nginx コンテナからの Proxy アクセスで PHP アプリケーションが利用できるようにする。
PHP-FPM コンテナ
php-fpm の Docker イメージをベースにしてコンテナを作成。あわせて phpinfo() を表示する PHP ファイルを先ほどの Apache のときと同じようにコピーする。
FROM php:fpm
COPY index.php /var/www/html/
<?php
phpinfo();
イメージの作成とコンテナ起動。ここでは phpfpm という名称で起動した。
php:fpm の Docker コンテナな PHP-FPM を tcp:9000 で待ち受けするとのことだが、Nginx からの Proxy アクセスのみを考慮しているので、Docker 起動時のポートマッピングオプションは必要なしになる。
$ docker build -t sandbox-phpinfo-phpfpm ./phpfpm
$ docker run --name phpfpm -d sandbox-phpinfo-phpfpm
Nginx コンテナ
Nginx イメージ を使う。
PHP-FPM への Proxy アクセスのためのサーバ設定ファイルを用意して、コンテナをビルドする際に設定ファイルディレクトリへファイルを埋め込む。
FROM nginx
ADD server.conf /etc/nginx/conf.d/server.conf
Proxy 設定ファイルは以下のとおり。
ここでポイントなのが、Proxy 先となる PHP-FPM のホストを 127.0.0.1 などの IP, hostname ではなく、Docker のコンテナ間接続のための機構である link オプションによるエイリアス名を指定することになる。ここでは php
という名称にした。 ("fastcgi_pass php:9000;" の箇所)
server {
listen 80 default;
server_name _;
root /var/www/html;
index index.php index.html index.htm;
charset utf-8;
access_log off;
error_log off;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
イメージの作成とコンテナ起動。
前述したコンテナ間接続のため、link オプションで <コンテナ名>:<エイリアス名> を指定する。phpfpm コンテナに対して Nginx 設定ファイル内で php というエイリアス名を使っているので、 --link phpfpm:php
となる。
$ docker build -t sandbox-phpinfo-nginx ./nginx
$ docker run --name nginx -p 80:80 --link phpfpm:php -d sandbox-phpinfo-nginx
動作確認
Apache + PHP の時と同様、Docker ホストへブラウザでルートアクセスすると、PHP-FPM による phpinfo() が表示される。
サンプルソース
今回利用したサンプルソース。