Laravelで作ったWebアプリを公開

作成: 2020年03月28日

更新: 2021年07月08日

経緯

かつてはDjangoでこのサイトを作成していたが、VueやらWebpackやらの新しい技術を使ってみようとするたび壁にぶち当たってしまったため
Laravelに移行した。

2021/7/8 追記

今はphp-fpmの公式Dockerfileを使用しています。
最新版はbana118/banatech_laravelを参照してください。

デプロイ方法

ローカルでの起動方法およびデプロイ方法は以下のREADME参照。
bana118/banatech_laravel
ドメイン等は変更する必要がある。
laravelのほかにnginx、php-fpm、supervisor(nginx、php-fpm実行用)を用いた。
本番環境の構築方法を忘れると困るのでDockerを主に使用して再現性をもたせた。

Dockerfile

docker-composeなどを用いればより簡潔に記述できるがここでは泥臭くDockerfileに手順を一つ一つ記述した。

Dockerfile#imagename: banatech_laravel
FROM ubuntu:18.04

# avoid freeze while configuring tzdata 
ENV DEBIAN_FRONTEND=noninteractive

#Author
MAINTAINER banatech

CMD echo "now running..."

# Install required packages and remove the apt packages cache when done.
RUN apt update && \
    apt upgrade -y && \
    apt install -y \
    curl \
    git \
    nano \
    vim-nox \
    nginx \
    supervisor \
    nodejs \
    npm \
    composer \
    php \
    php-zip \
    php-xml \
    php-json \
    php-mbstring \
    php-mysql \
    php-sqlite3 \
    php-bcmath \
    php-fpm \
    certbot \
    sqlite3 && \
    rm -rf /var/lib/apt/lists/*

# update node npm
RUN npm install n -g
RUN n stable
RUN apt purge -y nodejs npm
ENV PATH $PATH:/usr/local/bin/node
# add our code
COPY . /home/docker/code/banatech_laravel

# install packages, but it doesn't work so do it manually in docker

# install laravel and etc
# RUN cd /home/docker/code/banatech_laravel && composer install --optimize-autoloader --no-dev

# install npm packages
# RUN cd /home/docker/code/banatech_laravel && npm install

# clear laravel caches
# This app doesn't seem to delete the route cache...
# RUN cd /home/docker/code/banatech_laravel && php artisan config:cache
# RUN cd /home/docker/code/banatech_laravel && php artisan config:cache && php artisan route:cache

# generate app key
# RUN cd /home/docker/code/banatech_laravel && php artisan key:generate

# migrate
# RUN cd /home/docker/code/banatech_laravel && php artisan migrate

# compile css and js
# RUN cd /home/docker/code/banatech_laravel && npm run prod


# setup all the configfiles
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
COPY nginx-app.conf /etc/nginx/sites-available/default
COPY supervisor-app.conf /etc/supervisor/conf.d/

# create socket file for php-fpm
RUN mkdir /var/run/php
RUN touch /var/run/php/php7.2-fpm.sock
RUN chmod 777 /var/run/php/php7.2-fpm.sock

# run nginx
EXPOSE 80
EXPOSE 443
CMD ["supervisord", "-n"]

必要なものをaptでインストールしてsupervisorを用いてnginx, php-fpmを実行した。
supervisord-app.confは以下

supervisor-app.conf[supervisord]
nodaemon=true

[program:php-fpm]
command = /usr/sbin/php-fpm7.2 -c /etc/php/7.2/fpm
autostart=true
autorestart=true

[program:nginx]
command=/usr/sbin/nginx
autostart=true
autorestart=true

またnginxは一度以下のnginx-app.conf.tempを設定ファイルとして用いてhttpのみでデプロイし、letsencryptで証明書を取得してからnginx-app.conf.prodに切り替えてhttpsに対応した。

nginx-app.conf.temp# nginx-app.conf

#letsencrypt認証用
# configuration of the server
server {
    # the port your site will be served on, default_server indicates that this server block
    # is the block to use if no blocks match the server_name
    listen      80;
    # the domain name it will serve for
    server_name banatech.net; # substitute your machine's IP address or FQDN
    root /home/docker/code/banatech_laravel/public;
    charset     utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    index index.php index.html index.htm;

    #letsencrypt認証用
    location /.well-known {
        root /home/docker/code/banatech_laravel/public;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
nginx-app.conf.prod# nginx-app.conf

# 本番用
# http redirect
server {
    listen 80;
    listen [::]:80;
    server_name banatech.net;
    location /.well-known {
        root /home/docker/code/banatech_laravel/public;
    }
    #sitemap
    location /sitemap.xml {
        return 301 https://banatech.net/sitemap.xml;
    }

    #robots
    location /robots.txt {
        return 301 https://banatech.net/robots.txt;
    }

    location / {
        return 301 https://banatech.net;
    }
}

# configuration of the server
server {
    # the port your site will be served on
    listen      443 ssl http2;
    listen [::]:443 ssl http2;
    # ssl config
    ssl_certificate     /etc/letsencrypt/live/banatech.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/banatech.net/privkey.pem;

    #config https://jyn.jp/ssl-aplus/
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    #add_header Strict-Transport-Security 'max-age=31536000;';
    #ssl_dhparam /home/docker/code/dhparam/dhparam1024.pem;
    #ssl_dhparam /home/docker/code/dhparam/dhparam2048.pem;
    ssl_dhparam /home/docker/code/dhparam/dhparam4096.pem;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/banatech.net/chain.pem;
    # the domain name it will serve for
    server_name banatech.net; # substitute your machine's IP address or FQDN
    charset     utf-8;

    root /home/docker/code/banatech_laravel/public;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    index index.php index.html index.htm;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

https用のnginxの設定に関してはMozilla SSL Configuration Generatorおよびデプロイ 6.x Laravel - ReaDoubleを参考にした。
これで定番のssl評価サイトSSL Server Testで評価Aを取得できる。
screen.png
HSTS(HTTP Strict Transport Security)というhttp接続をほとんど拒否する設定などをしていないのでA+にはできていないがこれで十分だと思う。

詰まったところ

できればdocker runするだけでデプロイしたかったがdockerでマウントするとホスト側のファイルでコンテナ側のファイルが上書きされてしまうため、composerやnpmでインストールしたものがすべて消えてしまう。アップロードファイルの管理のためマウントは行いたいので仕方なくデプロイ後にコンテナに入ってcomposer install やnpm install を行った。dockerでマウントしたときにファイルはできるだけマージして欲しかった。
またデプロイ後にsupervisorctl statusするとどうもphp-fpmが死んでいるが、supervisor
からphp-fpmを外すとエラーがでる。これは何が原因かわからないがまあ動いているからヨシ!