めもめも のーと

ハマったこととか、覚えたこととか

Laravelアプリをサブディレクトリで動かした

ある要件でlaravelアプリをドメインURLのサブディレクトリで動かしたかったが、 ネットで調べてヒットした記事が、環境差異なのか、ことごとくハマらず動かなかったので、 最終的に動くようになった設定を公開しておく。

やりたいこと

環境

docker-composeにて以下のコンテナを作成。ちなみにホストはWindows10なので、docker for windowsを使用。

  • nginx
  • php-fpm

ホスト側のディレクトリ構成

myapp/
├── docker-compose.yml
├── html
│   └── laravelapp
        ├── public
            ├── index.php
├── nginx
│   ├── default.conf
│   └── nginx.conf
└── php
    ├── Dockerfile
    ├── php.ini
    └── run.sh
  • nginxとphp-fpmを別々のコンテナで動かすので、各コンテナがlaravelアプリ見にいけるように共有のディレクトリhtmlを用意し、そこにlaravelのアプリをおく。

docker-composeの設定

version: '3'
services:
  nginx:
    image: nginx:alpine
    ports:
      - "19080:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./html:/var/www/html
    depends_on:
      - phpapp
  phpapp:
    build: ./php
    volumes:
      - ./html:/var/www/html
      - ./php/php.ini:/usr/local/etc/php/php.ini
  • nginxのconf設定ファイルはホストで用意したものを反映させるためにvolumesに追記した。
  • DocumentRootは/var/www/htmlとし、ホスト側のhtmlディレクトリと対応させた。
  • またphp-fpmコンテナからもlaravelアプリが見れるようにするため、nginxのDocumentRootと同じディレクトリを見るようにした。
  • 今回はphp.iniも自前のものを使いたかったので、volumesにおいてコンテナに反映させた。

nginxの設定

nginx.conf内でincludeされるdefault.confに設定を追記したが、nginxが動けばどこに書いてもいいと思う。

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log debug;

    root   /var/www/html;

    location ~ ^/laravelapp/(.+\.(?:gif|jpg|css|png|svg)$) {
        alias /var/www/html/laravelapp/public/$1;
        break;
    }

    location ~ ^/laravelapp((/)?(.+))?$ {
        alias /var/www/html/laravelapp/public/; # 最後に / が必要

        index index.php; # serverディレクティブ直下に書いてもOK

        try_files $uri $uri/ @admin;

        location ~ [^/]\.php(/|$) {
            # (.+\.php) => $fastcgi_script_name   (/.*) => $fastcgi_path_info
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            # FastCGIサーバへリクエストをプロキシする
            fastcgi_pass phpapp:9000;
            # / で終わるURIの後に追加されるファイル名を設定
            fastcgi_index index.php;
            # 設定ファイル読み込み
            include fastcgi_params;
            # FastCGIサーバへ送られるパラメタ
            fastcgi_param SCRIPT_FILENAME ${document_root}index.php;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

    location @admin {
        rewrite /laravelapp(.*)$ /laravelapp/index.php$1 last;
    }
}
  • 重要なのは、locationディレクティブ内でaliasでパスを指定しているところ。
    • 今回のディレクトリ構成の場合、rootを使うとどうやってもうまくいかなかった。
    • パス指定の最後に / が無いとアクセスが publicindex.phpのように解釈されて動かなかった。
  • 解釈が合っているか分からないが、
    • try_filesで@adminが適用されるとrewriteがかかり、laravelapp/index.phpへのアクセスになる。
    • そうすると location ~ [^/].php(/|$) のディレクティブに合致し、php-pfmへアクセスが流れる。
    • laravelはpublic/index.phpがフロントコントローラとして動くがURLにindex.phpは通常含めないので、上記のようなrewrite設定が必要になる。
    • その際、URLにindex.phpは含まれないので、nginx側でindex index.phpの設定をしている。

php-fpmの設定

Dockerfileの中身は下記の通り、ホスト側で用意したスクリプトrun.shをコンテナ内で実行する。

Dockerfile

FROM php:7.1.8-fpm

ADD run.sh /tmp/run.sh
RUN chmod +x /tmp/run.sh && sh /tmp/run.sh

run.sh

#/bin/bash

apt-get update && apt-get install -y \
  git \
  zip \
  unzip \
  libpq-dev \

# install composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# install laravel
composer global require "laravel/installer=~1.1"

ちなみにlaravelアプリはphp-fpmコンテナができたらコンテナ内に入ってcreate-projectで新規作成するか、既存のソースコードをmyapp/htmlの直下に置く。

ここまできたらdockerを起動してコンテナを作る。

$ docker-compose up -d

http://localhost:19080/laravelapp/ をブラウザで開き、Laravelトップ画面が出たら成功。

ちなみに最後のスラッシュ(トレイリングスラッシュ=trailing slash)をなくしたい場合は、nginx側で別途設定が必要。

その他はまったところ

サブディレクトリでの動作に直接は関係ないが、今回のdocker構成ではまったところをメモ。

  • セッションが保持されない
    • => php.iniを見ると「session.auto_start = 0」であった。1に変更する。

サブディレクトリ対応はApacheでやればaliasを設定するだけですぐできたが、nginxは一筋なわではいかなかった。。