Posted at
LaravelDay 14

Laravelで最適なDocker環境を作る

More than 1 year has passed since last update.

この記事はこちら の構成の具体的な説明となります


ディレクトリ、ファイル構成

├── docker

│   ├── docker-compose.yml
│   ├── composer
│   │   └── Dockerfile
│   ├── data
│   │   └── Dockerfile
│   ├── fpm
│   │   ├── Dockerfile
│   │   └── php-fpm.d
│   │   ├── docker.conf
│   │   ├── www.conf
│   │   ├── www.conf.default
│   │   └── zz-docker.conf
│   ├── gulp
│   │   └── Dockerfile
│   ├── nginx
│   │   ├── Dockerfile
│   │   └── config
│   │   ├── laravel.conf
│   │   ├── nginx.conf
│   │   └── nginx_run.sh
│   └── npm
│   └── Dockerfile
├── logs
└── www


各種説明

こちらは各プロセスごとにディレクトリを分割し、それ専用のDockerfileを作成、docker-compose.ymlでそれらのビルド設定を記載し、一括ですべての環境を開始できるようにしています。


docker-compose.yml

version: "2" # docker-composeのversion2を使用

services: # 各種サービスの設定
data: # データボリューム用コンテナ、ソースやDBのデータ等開発で生成するものはここにマウント
build: ./data
volumes:
- ../:/data
- /var/lib/mysql
db: # DBストア
image: mariadb
volumes_from:
- data
environment:
MYSQL_ROOT_PASSWORD: pass
fpm: # php-fpm: PHPプロセスを実行するコンテナ
build: ./fpm
volumes_from:
- data
nginx: # php-fpmにリバースプロキシする
build: ./nginx
volumes_from:
- data
links:
- fpm:fpm
ports:
- "80:80"
composer: # composerコマンドを実行するときに都度実行
build: ./composer
volumes_from:
- data
gulp: # gulpコマンドを実行するときに都度実行
build: ./gulp
volumes_from:
- data
npm: # npmコマンドを実行するときに都度実行
build: ./npm
volumes_from:
- data


db

FROM debian:jessie

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

RUN mkdir -p /data
VOLUME ["/data"]
CMD ["true"]

このように/dataディレクトリを作成し、そこにボリュームマウントできるようにしているだけです。

使用しているimageはdebian:jessieを使っていますが、これは他のサービスもこれを使っているからで、他のimadeでも問題ありません。


fpm

FROM php:7.0.12-fpm

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

RUN apt-get update -y

# clean fpm conf
# RUN rm /usr/local/etc/php-fpm.d/*
COPY php-fpm.d /usr/local/etc/php-fpm.d

RUN mkdir -p /data
VOLUME ["/data"]

phpのDockerhubで公式にfpm用のimageを提供しているので、そちらを使っています。

ちなみにgithub上に元のDockerfileがあります。

なるべく最新のpackageを使いたいので、apt-get updateを行い、php-fpm.dに設置してあるfpm用の設定ファイルをコピーしています。


nginx

FROM nginx

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

COPY config/nginx.conf /etc/nginx/nginx.conf
COPY config/laravel.conf /etc/nginx/conf.d/laravel.conf
RUN rm /etc/nginx/conf.d/default.conf

RUN mkdir -p /data
VOLUME ["/data"]

nginxではphp-fpmを使用するため若干トリッキーなことをしています。

というのも、nginxからfpmのコンテナに向けてリバースプロキシをするために、サーバーのホスト名・ポート番号を下記のように指定する必要があるのですが

http {

upstream phpfpm_backend {
server fpm:9000;
}
...
}

このfpmというのが、fpmサービスが提供しているもので、同じdocker-compose内だとこのサービス名がホスト名の名前解決に使われます。

またlogの出力先として/data/logsを指定しているので、実行後のログはホストのlogsディレクトリに逐一反映されます


nginx.conf

    access_log /data/logs/access.log;

error_log /data/logs/error.log warn;


gulp

FROM debian:jessie

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

RUN apt-get update -y
RUN apt-get install -y curl git
RUN curl -sL https://deb.nodesource.com/setup | bash --
RUN apt-get install -y nodejs
RUN npm update -g npm
RUN npm cache clean
RUN npm i -g n
RUN n stable
RUN apt-get purge -y nodejs npm
RUN npm i -g gulp-cli

RUN mkdir -p /data/www
VOLUME ["/data"]
WORKDIR /data/www

ENTRYPOINT ["gulp"]
CMD ["-h"]

最新のnodejsをinstallし、npmを最新にしています。

nパッケージを使用しているのは、apt-getに乗っかっているnodeだとgulpをインストールするバージョンに達しないため、nパッケージを使ってnodejsのバージョンを上げています。

ただ、nパッケージをインストールするにはnodejsとnpmが必要なため、一時的にインストールし、あとでpurgeしています。

ENTRYPOINTをgulp、CMDを-hとすることによって

docker-compose run gulp

と実行すればgulp -hが実行され、

docker-compose run gulp <command>

とすればgulp <command>が実行されます。


npm

FROM debian:jessie

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

RUN apt-get update -y
RUN apt-get install -y curl git
RUN curl -sL https://deb.nodesource.com/setup | bash --
RUN apt-get install -y nodejs
RUN npm update -g npm
RUN npm cache clean
RUN npm i -g n
RUN n stable
RUN apt-get purge -y nodejs npm

RUN mkdir -p /data/www
VOLUME ["/data"]
WORKDIR /data/www

ENTRYPOINT ["npm"]
CMD ["-h"]

構造としてはgulpとほぼ同じです。

完全に別にしていますが、このnpmのdockerfileをビルドしたものをどこかのレジストリにpushしておき、npmとgulpで同じimageをFROMに設定することでDRYにすることが可能です。


composer

FROM php:7.0.12

MAINTAINER "Kota Matsumoto" <kota1861@gmail.com>

WORKDIR /tmp

RUN apt-get update -y
RUN apt-get install -y git unzip
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
RUN composer self-update
RUN composer global require hirak/prestissimo

RUN mkdir -p /data/www
VOLUME ["/data"]
WORKDIR /data/www

ENTRYPOINT ["composer"]
CMD ["--help"]

こちらはcomposerを使用するだけなので、使用するimageは純正のimage(fpmとか入っていない)を使っています。

composerをcurlコマンドで取得後、実行可能な場所に設置するのですが、このディレクトリはこのコンテナだけが参照できるので、他のサービスではcomposerを使用することはできません。

composerの各パッケージを並列にインストールできるようhirak/prestissimoをインストールしています。

composerの実行対象ディレクトリは/data/wwwですので、ここをworkdirとしています。

composerはキャッシュ機構があるので、複数人で開発をする場合は、都度composerの実行後コンテナをimageに固め、レジストリにpushすることで、各パッケージのインストール時間を軽減できます。

gulpと同様

ENTRYPOINTをcomposer、CMDを-hとすることによって

docker-compose run composer

と実行すればcomposer -hが実行され、

docker-compose run composer <command>

とすればcomposer <command>が実行されます。


使用方法

dockerディレクトリでdocker-composeコマンドを使用します。


# 各デーモン系コンテナの起動
docker-compose up -d

# laravelのインストール
docker-compose run --rm composer create-project laravel/laravel

# npmコマンドの実行(elixir等のインストール)
docker-compose run --rm npm install

# gulpでライブコーディング
docker-compose run --rm gulp watch

# composerパッケージのアップデート
docker-compose run --rm composer update


まとめ

このように各サービス、プロセスごとに分割することで、それぞれのサービスを独立して管理することができ、開発に集中することができます。

LaravelではhomesteadというVagrantで動くものを提供していますが、Docker for Mac等Dockerをローカルで使用できる環境が整ってきたので、起動スピードの早いDockerを使うのが何かと便利かとおもいます。