どうも、若松です。

前回はLaravelをDockerで起動し、イメージを軽量化するところまで行いました。
https://cloudpack.media/48190

今回は、php artisanでのサーバ起動ではなく、Nginx+php-fpmでLaravelを表示するところまでを行います。

設定

ディレクトリ構造

docker/
├─ docker-compose.yml
├─ nginx/
|  ├─ Dockerfile
|  └─ default.conf
└─ laravel/
   └─  Dockerfile

docker-compose.yml

version: '2'
services:
  nginx:
    image: nginx
    ports:
      - "80:80"
  laravel:
    image: laravel

Dockerfile(nginx)

FROM nginx:1.17-alpine

# ローカルから設定ファイルをコピー
COPY  default.conf /etc/nginx/conf.d/default.conf

default.conf(nginx)

server {
    listen       80;
    server_name  localhost;

    location / {
        # ドキュメントルート設定
        root   /var/www/laravel/public;

        fastcgi_split_path_info  ^(.+\.(?:php|phar))(/.*)$;   
        fastcgi_intercept_errors on;

        fastcgi_index  index.php;
        include        fastcgi_params;
        # FastCGIの向き先をLaravelコンテナに設定
        fastcgi_pass   laravel:9000;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO $fastcgi_path_info;
        fastcgi_param  PATH_TRANSLATED $document_root$fastcgi_path_info;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile(laravel)

FROM amazonlinux:2 as vender

# PHPインストール
RUN amazon-linux-extras install -y php7.3
RUN yum install -y php-pecl-zip php-mbstring php-dom

# Composerインストール
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer

# 環境変数設定
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME "/opt/composer"
ENV PATH "$PATH:/opt/composer/vendor/bin"

# Laravelインストール
RUN composer global require "laravel/installer"

# Laravelプロジェクト作成
WORKDIR /var/www
RUN composer create-project laravel/laravel laravel

FROM php:7.3-fpm-alpine

# ビルド用コンテナから必要なコンテンツをコピー
COPY --from=vender --chown=www-data:www-data /var/www/ /var/www/

操作

コマンドは全て最上位ディレクトリの dockerから行う想定です。

Nginxコンテナビルド

docker build nginx/. -t nginx --squash

Laravelコンテナビルド

docker build laravel/. -t laravel --squash

docker-composeで起動

docker-compose up

ブラウザで表示を確認

http://localhost:8000 にアクセスすることで以下のサンプルを表示します。

解説

Nginxコンテナ

ベースイメージ

FROM nginx:1.17-alpine

ベースイメージにはNginx公式リポジトリにあるnginx:1.17-alpineを使用しました。
2019/7/14現在のNginxの最新が1.17であり、軽量化を目的にAlpineLinux版を使いたかったためです。
80番ポートの開放やNginxの起動についてはベースイメージ内で既に設定されているため、今回のDokcerfileには記述していません。

default.conf

COPY  default.conf /etc/nginx/conf.d/default.conf

設定はローカルに用意したdefault.confをイメージにコピーして配置します。
FastCGI設定のほとんどは一般的な設定のため、特徴的なものだけ解説します。

root
root   /var/www/laravel/public;

ドキュメントルートはLaravelコンテナのアプリケーションが配置されているディレクトリを指定します。

fastcgi_pass
fastcgi_pass   laravel:9000;

UnixソケットかTCPを指定できますが、Unixソケットではコンテナを越えられないため、TCPで設定します。
アドレスの指定にはDockerのNamespaceを利用します。

Laravelコンテナ

前回のDockerfileからの差異のみ解説します。

ベースイメージ

FROM php:7.3-fpm-alpine

実行用イメージのベースを php:7.3-alpineからphp:7.3-fpm-alpineに変更しました。
これによってデフォルトでphp-fpmがインストールされた状態から設定を行えばよくなります。
9000番ポートの開放やphp-fpmの起動についてはベースイメージ内で既に設定されているため、今回のDokcerfileには記述していません。

Laravelコンテンツのオーナー変更

COPY --from=vender --chown=www-data:www-data /var/www/ /var/www/

php:7.3-fpm-alpineのphp-fpm初期設定では、php-fpmのワーカ起動ユーザはwww-dataになっています。
COPYコマンドで配置したLaravelコンテンツはrootがオーナーになってしまうため、そのままだと権限エラーとなります。
そこで、--chownオプションを使用し、オーナーをwww-dataへ変更しています。
--chownオプションはBashでいうところのchown -Rとなるため、ディレクトリがあっても再帰的に処理してくれます。

docker-compose

今回からコンテナが2つになったため、操作簡略のためにdocker-composeを導入しました。
docker-composeには起動時のオプション設定や、複数コンテナのビルド、依存関係制御など様々な機能がありますが、ここではコンテナ起動/停止とポートオプションのみ使用しています。

複数コンテナのビルドを使用しない理由

本当であれば使用したかったのが本音です。
しかしながら2019/7/14現在、BuildKitやsquashオプションに対応していないため、あえてdockerコマンドでビルドを行っています。

Tips

コンテナイメージ内にあるファイルをローカルにコピーする

設定ファイルを作成する際に、デフォルトの設定をローカルにコピーし、それを改変して作成していくことはよくあると思います。
コンテナではSCPが使えないため、代わりにdocker cpコマンドを使用します。
今回のdefault.confの場合は、以下のようにしてコピーしました。

docker run -d --name nginx nginx:1.17-alpine
docker cp $(docker ps --filter name=nginx -aq):/etc/nginx/conf.d/default.conf .

コンテナイメージの履歴を確認する

FROMで使用するベースイメージには予めポートの開放やデーモンの起動が設定されている場合があります。
今回でいうところのNginxやphp-fpmですね。
それを確認するにはdocker historyコマンドを使用します。
例としてphp-fpmのhistoryを確認してみます。

docker history --format {{.CreatedBy}} php:7.3-fpm-alpine
/bin/sh -c #(nop)  CMD ["php-fpm"]
/bin/sh -c #(nop)  EXPOSE 9000
/bin/sh -c #(nop)  STOPSIGNAL SIGQUIT
/bin/sh -c set -eux;  cd /usr/local/etc;  if…
/bin/sh -c #(nop) WORKDIR /var/www/html
/bin/sh -c #(nop)  ENTRYPOINT ["docker-php-e…
/bin/sh -c docker-php-ext-enable sodium
...

このようにズラズラとコマンドが表示されるかと思います。
これは実行日次のtimestampが新しい順で上から並んでいます。
これを見るとベースイメージの最後に、9000番ポートの開放とphp-fpmの実行が行われているため、今回のDockerfileではポートの開放とデーモンの起動が不要なことがわかります。

まとめ

Nginx+php-fpmに加えて、docker-composeも導入してみました。
そんなに特殊な設定を行ったわけではありませんが、Dockerfileの書き方やコンテナ特有の設定等はお伝えできたかと思います。

元記事はこちら

Nginxとphp-fpmを用いてLaravalを表示する