Laravel5をDockerで動かす
Laravel5で構築したアプリケーションの開発環境をDocker化するための方法を紹介する.
サンプルアプリケーションはこちらで確認できる.
準備
以下の環境でLaravel5が動作するように, 環境を構築する.
- OS
- Ubuntu 14.04
- ミドルウェア
- Nginx
- php-fpm 5.5
- MySQL 5.5
Laravel5のインストール
まず, laravel5をインストールする. インストールにはcomposerを用いる. create-projectの時に, dev-developを指定するとインストールできる.
mkdir dockerized-laravel5
cd dockerized-laravel5
composer create-project laravel/laravel application dev-developPHPコンテナ
nginx+php-fpmな環境で, laravelが動作するようにDockerfileを記述する.
Dockerでは, 1コンテナ1プロセスにするのが好ましいが, 今回はnginxとphp-fpmを1コンテナで動かすために, supervisordをもちいる.
Dockerfileは以下のとおり.
FROM ubuntu:14.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN apt-get install -yq --force-yes build-essential wget curl git ssh nginx nodejs-legacy npm mysql-client supervisor
RUN apt-get install -yq --force-yes php5-cli php5 php5-fpm php5-mysql php5-curl php5-mcrypt php5-memcached && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN php5enmod mcrypt
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN mkdir -p /app
WORKDIR /app
ADD ./application/database /app/database
ADD ./application/tests /app/tests
ADD ./application/composer.json /app/composer.json
ADD ./application/composer.lock /app/composer.lock
RUN composer install --no-scripts
ADD ./application /app
RUN php artisan clear-compiled
RUN php artisan optimize
RUN usermod -u 1000 www-data
RUN groupmod -g 1000 www-data
RUN chown -R www-data:www-data /app
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
ADD docker/nginx-site.conf /etc/nginx/sites-available/default
ADD docker/supervisord.conf /etc/supervisord.conf
EXPOSE 80
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]supervisord.conf
[unix_http_server]
file=/tmp/supervisor.sock
[supervisord]
logfile=/tmp/supervisord.log
pidfile=/tmp/supervisord.pid
nodaemon=false
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[program:php5-fpm]
command=/usr/sbin/php5-fpm -c /etc/php5/fpm --nodaemonize
[program:nginx]
command=/usr/sbin/nginxこのDockerfileのポイントについて説明する.
composer.jsonを先にADDする
ADD ./application /appを行ったあとにRUN composer installとすると, composer.jsonの変更の有無にかかわらず, ./application内のどれかのファイルが変更されるごとに composer installが走る.
そこで, 先にADD ./application/composer.json /app/composer.jsonとRUN composer installを行って, その後に/applicationをADDすることで, composer.jsonに変更がない場合は, その行がキャッシュされる.
これは, RubyのBundlerで紹介されているテクニックをそのまま用いている.
ただし, composerの場合はそのままではうまくいかない. 問題は2つある.
composer.jsonのautoloadに指定されたclassmapに対応するクラスは,composer install時に存在する必要がある.composer install後に,composer.json内のscriptsに記述された処理が実行される.
この対処方法について述べる.
composerのautoloadに対応する
まず, composer.jsonのautoloadに対応する. といっても, composer install時にautoloadが必要とするクラスが存在するだけでOKなので,
application内の, databaseとtestsディレクトリをADDすれば良い.
ADD ./application/database /app/database
ADD ./application/tests /app/testscomposerのscriptsに対応する
comopserは, 実行後に特定の処理を実行するためのフックが存在する. 具体的にはcomposer.json内のscriptsの項目の処理が実行される.
laravelでは, composer install後に, 以下の処理が実行される.
php artisan clear-compiled
php artisan optimizeartisanは, laravelのコマンドラインツールだが, これはlaravelのアプリケーションディレクトリが存在しないと実行できない.
上記のテクニックでは, composer install時には./application内のすべてのファイルが存在しないため, artisanが正常に実行できずにエラーとなる.
この問題は, composer install実行後に, scriptsに記述された処理を行わず, laravelのアプリケーションディレクトリを追加後に, scriptsの処理を行うことで対処できる.
具体的には, composer installを--no-scripts付きで実行し, ./applicationをADDした後に, scriptsの項目の処理を実行する.
RUN composer install --no-scripts
ADD ./application /app
RUN php artisan clear-compiled
RUN php artisan optimize.dockerignore
Dockerfileとは直接は関係ないが, Dockerコンテナに含める必要のないファイルやディレクトリは, .dockerignoreに記述することで, ADDやCOPYの対象から外れる.
.gitなどは省いておくのと, laravelアプリケーションディレクトリ内の, vendorとcomposer.lockも対象から省いておかないと, Dockerコンテナ側でビルドした内容と, Dockerホスト側のディレクトリには差異が生じて, アプリケーションが動かない可能性がある.
MySQLコンテナ
この記事と同様に, Docker Hub公式のhttps://registry.hub.docker.com/_/mysql/を用いる.
dockerized-laravel5直下にfig.xmlを用意し, 以下のように記述する.
環境変数をenvironment:に設定することで, MySQLの設定を変更することができる.
また, my.cnfなどの設定を変更したい場合は, Dockerコンテナ内の/etc/mysqlに, ローカルのディレクトリをマウントすることで設定を置き換える方法もある(/path/to/mysql:/etc/mysqlをvolumesに追記する).
fig.yml
以上のDockerfileからPHPコンテナを立ち上げるためのFigの設定を示す. dockerized-laravel5ディレクトリ直下に, 以下の様な内容のfig.ymlを設置する.
db:
image: mysql:5.5
environment:
- MYSQL_ROOT_PASSWORD=himitsunopassword
ports:
- "3306"
volumes:
- /var/lib/mysql
web:
build: .
ports:
- "8080:80"
volumes:
- ./application:/app
links:
- db開発用途で利用するために, volumes項目に, ./application:/appと記述する. こうすることで, ローカルでファイルを編集した内容が即座にDockerコンテナ内に反映される.
PHPコンテナとMySQLコンテナのリンクと設定
上記の設定では, Dockerのlink機能を用いて, PHPコンテナからMySQLコンテナ内のデータベースを利用できるようになっている.
アプリケーションからMySQLコンテナのDBに接続するための設定は, 環境変数を経由して取得できる.
環境変数の一覧は, 以下のように確認できる.
$ docker exec -it dockerizedlaravel5_web_1 env
DB_1_PORT_3306_TCP_ADDR=172.17.0.13
DB_1_PORT_3306_TCP_PORT=3306
DB_1_NAME=/dockerizedlaravel5_web_1/db_1
DB_1_ENV_MYSQL_ROOT_PASSWORD=himitsunopasswordlaravelのデータベースの設定は, env関数を利用して行う.
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_1_PORT_3306_TCP_ADDR', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_1_ENV_MYSQL_ROOT_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],開発環境として利用する
figで管理しているコンテナの状態は, fig psで確認できる.
$ fig ps
Name Command State Ports
--------------------------------------------------------------------------------------------
dockerizedlaravel5_db_1 /entrypoint.sh mysqld Exit 0 0.0.0.0:49153->3306/tcp
dockerizedlaravel5_web_1 /usr/bin/supervisord -n -c ... Exit 0起動は, fig upで行う.
$ fig up
Recreating dockerizedlaravel5_db_1...
Recreating dockerizedlaravel5_web_1...
Attaching to dockerizedlaravel5_db_1, dockerizedlaravel5_web_1起動中のコンテナでコマンドを実行するにはdocker execを利用する.
$ docker exec dockerizedlaravel5_web_1 ./artisan route:list
+--------+--------------------------------+-------------------------------------------------------+------+------------------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+--------------------------------+-------------------------------------------------------+------+------------------------------------------------------------+------------+
| | GET|HEAD | / | | App\Http\Controllers\WelcomeController@index | |
| | GET|HEAD | home | | App\Http\Controllers\HomeController@index | |
| | GET|HEAD | auth/register/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\AuthController@getRegister | |
| | POST | auth/register/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\AuthController@postRegister | |
| | GET|HEAD | auth/login/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\AuthController@getLogin | |
| | POST | auth/login/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\AuthController@postLogin | |
| | GET|HEAD | auth/logout/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\AuthController@getLogout | |
| | GET|HEAD|POST|PUT|PATCH|DELETE | auth/{_missing} | | App\Http\Controllers\Auth\AuthController@missingMethod | |
| | GET|HEAD | password/email/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\PasswordController@getEmail | |
| | POST | password/email/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\PasswordController@postEmail | |
| | GET|HEAD | password/reset/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\PasswordController@getReset | |
| | POST | password/reset/{one?}/{two?}/{three?}/{four?}/{five?} | | App\Http\Controllers\Auth\PasswordController@postReset | |
| | GET|HEAD|POST|PUT|PATCH|DELETE | password/{_missing} | | App\Http\Controllers\Auth\PasswordController@missingMethod | |
+--------+--------------------------------+-------------------------------------------------------+------+------------------------------------------------------------+------------+また, コンテナ内にログインしたい場合は, docker execで, /bin/bashなどを実行する.
$ docker exec -it dockerizedlaravel5_web_1 /bin/bash
root@c489f074bb66:/app# ls
app artisan bootstrap composer.json composer.lock config database gulpfile.js package.json phpspec.yml phpunit.xml public readme.md resources storage tests vendorまとめ
LaravelをDockerで動かすための方法を紹介した.
また このテクニックをcomposerに応用するためのテクニックをいくつか示した.
次に, 用意したDockerfileを用いて, テスト・CI・デプロイについて紹介していきたい.