はじめに
興味本位で新しいフレームワークを試してみようと始めた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の構成はこんな感じ
- 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番で公開しました。
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としています。
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
[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としています。
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を有効にしたくらいです。
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
のシンボリックリンクだから
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
フォルダとしています。
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変更のみです。
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
のファイル修正
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 ps
でlaravel_phpのCONTAINER 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
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: