LoginSignup
7
8

More than 3 years have passed since last update.

laravel環境をDocker使って整える

Last updated at Posted at 2019-09-08

はじめに

興味本位で新しいフレームワークを試してみようと始めたLaravel
どうせなら本番環境はOpenShift、開発環境はDockerにしてみようと思ったのが運の尽き
今現在嵌っているポイントを解説しつつ環境構築をご紹介します。

環境

  • Windows10 Pro
  • docker for windows (docker desctop community) (ver.2.1.0.2)
  • VSCode
  • php7.2.22 for windows
  • composer

Laravel環境

Dockerの構成はこんな感じ

nginx-fpm-mariadb.png

  • laravel_nginx (based nginx:latest)
  • laravel_php (based php:7.2.8-fpm)
  • laravel_mariadb (based mariadb:10.4)
  • laravel_pma (based phpmyadmin/phpmyadmin:4.8)

dockerの定義

ローカルのディレクトリ構成はこんな感じにしました。

├─ laravel/
   ├─ mariadb/
   │  ├─ conf.d/
   │  │  └─ my.conf     # mariadb設定ファイル
   │  ├─ data/            # mariadbデータ永続化用
   │  └─ Dockerfile       # mariadb用Dockerfile
   ├─ nginx/
   │  ├─ etc/
   │  │  ├─ conf.d/
   │  │  │  └─ default.conf   # nginxサイト定義
   │  │  └─ nginx.conf          # nginx基本定義
   │  └─ Dockerfile               # nginx用Dockerfile
   ├─ php/
   │  ├─ log/
   │  │  └─ xdebug/    # xDebug用
   │  ├─ www/
   │  │  └─ laravel/   # laravelプロジェクト用
   │  │     :
   │  └─ Dockerfile      # php-fpm用Dockerfile
   ├─ phpmyadmin/
   │  ├─ sessions/       # セッションファイル管理用
   │  └─ Dockerfile      # phpmysqladmin用Dockerfile
   ├─ docker-compose.yaml  # 全てのdocker定義

docker-compose.yaml

全ての要、docker-compose.yamlはこんな形になりました。

  • nginxはポート80でlistenしています。
  • nginxはlaravelプロジェクトのpublicフォルダを/var/wwwで腹持ちさせました。
  • mariadbはデータ永続化のためmysql時代と同様のことをしようとしたのですが、InnoDB作成時にエラーが発生し起動しなかったため、現状仕方なしに揮発性としています。
  • phpはwww/laravelにlaravelプロジェクトをあらかじめ生成したものを腹持ちさせています。
  • php-fpmは9000番でnginxからの通信を受けます。
  • phpmyadminは8080番で公開しました。
docker-compose.yaml
version: '3'
services:
  nginx:
    container_name: laravel_nginx
    build: ./nginx/
    image: laravel_nginx
    ports:
      - 80:80
    links:
      - php
    depends_on:
      - php
    volumes:
      - ./php/www/laravel/public:/var/www

  mariadb:
    container_name: laravel_mariadb
    build: ./mariadb/
    image: laravel_mariadb
    ports:
      - 3306:3306
    volumes:
      - ./mariadb/data:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=laravel_db
      - MYSQL_ROOT_PASSWORD=root@1234
      - MYSQL_USER=laravel
      - MYSQL_PASSWORD=laravel@1234

  php:
    container_name: laravel_php
    build: ./php/
    image: laravel_php
    links:
      - mariadb
    volumes:
      - ./php/www/laravel:/var/www/laravel
      - ./php/log/xdebug:/var/log/xdebug
    stdin_open: true
    tty: true
    depends_on:
      - mariadb

  phpmyadmin:
    container_name: laravel_pma
    build: ./phpmyadmin/
    image: phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mariadb
      - PMA_USER=root
      - PMA_PASSWORD=root@1234
    ports:
      - 8080:80
    links:
      - mariadb
    volumes:
      - ./phpmyadmin/sessions:/sessions
    depends_on:
      - mariadb

それでは各Dockerの定義を見ていきましょう!

mariadb:10.4用Docker定義

ここではTZ変更および設定ファイルのCOPYのみのDockerfileとしています。

mariadb/Dockerfile
FROM mariadb:10.4

RUN mv /etc/localtime /etc/localtime.org && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

COPY ./conf.d /etc/mysql/conf.d
mariadb/conf.d/my.conf
[mysqld]
# Character code setting / collation order setting
character_set_server=utf8mb4
collation-server=utf8mb4_bin

collation_server = utf8mb4_ja_0900_as_cs

# Default Authentication Plugin
default_authentication_plugin=mysql_native_password

# Japan time
default-time-zone='+9:00'

[mysql]
default-character-set=utf8mb4

nginx:latest用Docker定義

ここも同じくTZ変更および設定ファイルのCOPYのみのDockerfileとしています。

nginx/Dockerfile
FROM nginx:latest

RUN mv /etc/localtime /etc/localtime.org && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

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

nginx.confの設定は、gzipを有効にしたくらいです。

nginx/etc/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log debug;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    server_tokens off;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_types image/png image/gif image/jpeg text/javascript text/css;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_comp_level 9;

    include /etc/nginx/conf.d/*.conf;
}

default.confの設定はとっても苦労してまだ嵌り中ですが…
laravelプロジェクトのpublicをrootとして、storage,js,cssはDockerの世界でnginxローカルに共有しようとしています。
ここでstorageのみうまく行っていません。
なぜなら別サーバー(php)上で定義されたlaravel/storage/app/publicのシンボリックリンクだから

nginx/etc/conf.d/default.conf
server {
    listen       80;
    server_name  _;

    root /var/www/laravel/public;
    index index.php;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;

    location ~ ^/(storage|js|css)/.*$ {
        root /var/www;
    }

    location = robots.txt {

    }

    location = favicon.ico {

    }

    location ~ \.(jpg|png|gif|swf|jpeg|ico)$ {

    }

    location ~ \.(css|js)$ {
        charset  UTF-8;

    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;

        # pass the PHP scripts to FastCGI server listening on php:9000
        #
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   php:9000;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
        }
    }

    # deny access to .* files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\. {
        deny  all;
    }
}

php:7.2.8-fpm用Docker定義

ここが本体の大事な部分。
TZ変更は他サーバーのDockerfileと同様ですが、
デバック環境を実現するため(まだ実現できていないけど…)にxdebugをインストールして、
php拡張モジュール(gd)を追加インストールするためにlibpng-devをインストールしています。

WORKDIRはlaravelプロジェクトのpublicフォルダとしています。

php/Dockerfile
FROM php:7.2.8-fpm

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get -y update && \
    pecl install xdebug && \
    docker-php-ext-enable xdebug && \
    mv /etc/localtime /etc/localtime.org && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

RUN apt-get -y install libpng-dev && \
    docker-php-ext-install pdo_mysql mysqli gd opcache

RUN apt-get autoremove && \
    apt-get clean

WORKDIR /var/www/laravel/public

本題となるlaravelプロジェクトはWindows上で生成したものを腹持ちさせましたが
その手順は、また改めて下の方で

phpmyadmin/phpmyadmin:4.8用Docker定義

mariadbの確認ツールとしてphpmyadminを準備しました。
ここはTZ変更のみです。

phpmyadmin/Dockerfile
FROM phpmyadmin/phpmyadmin:4.8

RUN mv /etc/localtime /etc/localtime.org && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

laravelプロジェクトの作成(Windows10)

毎回Dockerに入って作成するのも非常に時間がかかり嫌なので予めlaravelプロジェクトを作成しておきます。
と言うのもlaravelのvendorフォルダは.gitignoreで定義されていてgitにアップできません。
また親を抜いても子供のディレクトリがどんな定義入っているのかわからないので、Windows上で作成しました。

まずはphpのインストール

  • php公式サイトからphpのWindows10用イメージ(VC15 x64 Thread Safe (2019-Aug-28 12:32:22))をダウンロードし解凍します。
  • 解凍してできたphp.exeのあるディレクトリでコマンドプロンプトから以下の様に叩きます。面倒なのでPATH定義とか一切なし(笑)
C:\Users\tak>cd C:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64

C:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64>php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

C:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64>php composer-setup.php
All settings correct for using Composer
Downloading...

Composer (version 1.9.0) successfully installed to: C:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64\composer.phar
Use it: php composer.phar


C:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64>php -r "unlink('composer-setup.php');"

  • laravelプロジェクトのセットアップ(以下の例はc:\git\docker\laravelに上記構成があると思ってください)
c:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64>del c:\git\docker\laravel\php\www\laravel
 :
c:\Program Files\php\php-7.2.22RC1-Win32-VC15-x64>php composer.phar create-project --prefer-dist laravel/laravel c:\git\docker\laravel\php\www\laravel
Installing laravel/laravel (v6.0.1)
  - Installing laravel/laravel (v6.0.1): Loading from cache
Created project in c:\git\docker\laravel\php\www\laravel
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 84 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-ctype (v1.12.0): Loading from cache
  - Installing phpoption/phpoption (1.5.0): Loading from cache
  - Installing vlucas/phpdotenv (v3.5.0): Loading from cache
  - Installing symfony/css-selector (v4.3.4): Loading from cache
  - Installing tijsverkoyen/css-to-inline-styles (2.2.1): Loading from cache
  - Installing symfony/polyfill-php72 (v1.12.0): Loading from cache
  - Installing symfony/polyfill-mbstring (v1.12.0): Loading from cache
  - Installing symfony/var-dumper (v4.3.4): Loading from cache
   :
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
> @php artisan key:generate --ansi
Application key set successfully.
  • laravelの.envのファイル修正
php/www/laravel/.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:tvFNQBpu+DwjzGFqRZLWqsLFTJvLCla7f1QFuxmunDY=
APP_DEBUG=true
APP_URL=http://127.0.0.1   # dockerローカル環境なのでこの値

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=mariadb            # docker-compose.yamlに記載したmariadbのservice名
DB_PORT=3306               # docker-compose.yamlに記載したmariadbのport番号
DB_DATABASE=laravel_db     # docker-compose.yamlに記載したMYSQL_DATABASE
DB_USERNAME=laravel        # docker-compose.yamlに記載したMYSQL_USER
DB_PASSWORD=laravel@1234   # docker-compose.yamlに記載したMYSQL_PASSWORD

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

Dockerの起動

ここまで準備ができたらdockerを起動します。

C:\Users\tak>cd C:\Git\docker\laravel
C:\Git\docker\laravel>docker-compose build
C:\Git\docker\laravel>docker-compose up

別のcmd.exeを起動しlaravel環境の最終整備を行います。
ここでいう最終整備とは
- dbのマイグレーション
- ファイルアップロードのAppを作るときなどに使うstorage/app/publicのシンボリックリンクをpublicに定義する
ことです。

今は空のプロジェクトだから意味はないのですが…
ちゃんと開発してくと必要と思われますので

まずはdocker pslaravel_phpCONTAINER IDを調べます。
下の例では「c26919066c7f」ですね。

C:\User\tak>docker ps
C:\Git\laravel-docker\laravel>docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
55aa5b00f6a0        laravel_nginx       "nginx -g 'daemon of…"   2 hours ago         Up 2 hours          0.0.0.0:80->80/tcp               laravel_nginx
565465863a19        phpmyadmin          "/run.sh supervisord…"   7 hours ago         Up 2 hours          9000/tcp, 0.0.0.0:8080->80/tcp   laravel_pma
c26919066c7f        laravel_php         "docker-php-entrypoi…"   7 hours ago         Up 2 hours          9000/tcp                         laravel_php
43881761e8b9        laravel_mariadb     "docker-entrypoint.s…"   7 hours ago         Up 2 hours          0.0.0.0:3306->3306/tcp           laravel_mariadb

ではコンテナ内に入ります。
先ほど調べたCONTAINER IDを引数にdocker execするとDockerfileで指定したWORKDIRにログインします。

C:\Git\laravel-docker\laravel>docker exec -it c26919066c7f /bin/bash
root@c26919066c7f:/var/www/laravel/public# 

artisanが置いてある一つ上のディレクトリに移動しそれぞれ実行します。

root@c26919066c7f:/var/www/laravel/public# cd ..
root@c26919066c7f:/var/www/laravel#

DBのマイグレーション

root@c26919066c7f:/var/www/laravel# php artisan migrate

storage/app/publicのシンボリックリンクをpublicに定義する

root@c26919066c7f:/var/www/laravel# php artisan storage:link

残課題

この週末の試行・調査で判明しなかった点は以下の2点です(´;ω;`)ブァァ

  • /js/app.jsへのアクセスができない。(nginxの設定見直し?)

  /js/app.jsが/js/app.js/になって/var/www/js/app.js/index.phpになっちゃう
  /js/test.jsはOK。何故なんだぁ~
  /css/app.cssは問題ない…なんでだろ

  • mariadbのデータ永続化 (docker-compose.yaml?) → 対策できた!
  • public/storageフォルダの公開 (nginx, docker-compose.yamlの見直し?)

残課題の状況 @2019.09.12

  • /js/app.jsへのアクセスができない問題

  結論:Chromeのキャッシュによるものでした。キャッシュクリアで正常にアクセスできました。
  nginx設定時に誤った設定をし何度か試したことが影響して勝手に/を補完していました。

  • mariadbのデータ永続化

  結論:docker-compose.yamlの書き方を変え、データ領域をコンテナ化することで実現できました。
  これはdocker for windows固有の問題のようです。

回避方法はこちらへ 『Docker for WindowsでMariaDBのデータを永続化

  • public/storageフォルダの公開

  結論:docker-compose.yamlの書き方を変え、
  ./php/www/laravel/storage/app/public:/var/www/storage
  とマウントすることで回避しました。

回避結果のdocker-compose.yaml

docker-compose.yaml
version: '3'
services:
  nginx:
    container_name: laravel_nginx
    build: ./nginx/
    image: laravel_nginx:latest
    ports:
      - 80:80
    links:
      - php
    depends_on:
      - php
    volumes:
      - ./php/www/laravel/public:/var/www
      - ./php/www/laravel/storage/app/public:/var/www/storage

  mariadb:
    container_name: laravel_mariadb
    build: ./mariadb/
    image: laravel_mariadb:10.4.7
    ports:
      - 3306:3306
    volumes:
      - dbvolume:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=laravel_db
      - MYSQL_ROOT_PASSWORD=root@1234
      - MYSQL_USER=laravel
      - MYSQL_PASSWORD=laravel@1234

  php:
    container_name: laravel_php
    build: ./php/
    image: laravel_php:7.2.8-fpm
    links:
      - mariadb
    volumes:
      - ./php/www/laravel:/var/www/laravel
      - ./php/log/xdebug:/var/log/xdebug
    stdin_open: true
    tty: true
    depends_on:
      - mariadb

  phpmyadmin:
    container_name: laravel_pma
    build: ./phpmyadmin/
    image: phpmyadmin:4.8
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mariadb
      - PMA_USER=root
      - PMA_PASSWORD=root@1234
    ports:
      - 8080:80
    links:
      - mariadb
    depends_on:
      - mariadb

volumes:
  - dbvolume:
7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8