かばちんのエンジニアブログ

日々の経験の中で培った内容を備忘録も兼ねて記録していくブログです。少しでも誰かの役に立つために頑張って続けていけたらなと思います。

Docker + Laravel + MariaDB + Redis での環境構築

f:id:kabatin:20160222190902p:plain

Scalaの開発環境の次に、手堅くPHPの開発環境も作ることになりました。
その手順とハマったポイントなどを備忘録として書いていきたいと思います。

前提条件

Macでの手順
MacVirtualBoxUbuntuがインストール済み
・Dockerもインストール済み
・docker-composeもインストール済み

参考)VirtualBoxUbuntuのインストールや、Dockerのインストール手順はこちらを参照
kabatin.hateblo.jp

参考)docker-composeのインストール手順はこちらを参照
kabatin.hateblo.jp


各ソフトウェアのバージョン情報など

MacOSX 10.11.1
VirtualBox 5.0.14
Ubuntu 14.04 LTS
・Docker 1.10.2
PHP 5.5.9
・Laravel 5.2
MariaDB 10.1.12
・Redis 3.0.5


フォルダ構成

まず完成形のフォルダ構成はこちら

.
├── data
│   └── php
├── docker-compose.yml
├── server
│   └── docker
│       ├── mariadb
│       │   ├── Dockerfile
│       │   └── docker-entrypoint-initdb.d
│       │       └── configure.sh
│       ├── nginx
│       │   ├── Dockerfile
│       │   └── conf
│       │       └── default.conf
│       ├── php
│       │   └── Dockerfile
│       └── redis
│           └── redis.conf
└── storage-compose.yml
MariaDB と Redis

まずは比較的簡単なデータベースとRedisの設定から行います。

設定するファイルはメインの docker-compose.yml とは分けて、storage-compose.yml とします。
中身はこんな感じになっています。

version: '2'

services:

  db:
    build: server/docker/mariadb
    volumes:
      - ./data/mariadb:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_PASSWORD: password
      MYSQL_USER: user1
      MYSQL_DB: password
    entrypoint:
      /docker-entrypoint-initdb.d/configure.sh

  redis:
    image: redis:3.0.5
    volumes:
      - "./server/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf"
    entrypoint:
     - "redis-server"
     - "/usr/local/etc/redis/redis.conf"

MariaDB, Redis 共通

version

このバージョンは "2" じゃないとダメなようです。
決められたものなので、おまじないとして記述しましょう。

build

Dockerfile が置いてあるパスを指定します。
最初にお見せしたツリーを見ると MariaDB 用の Dockerfile の場所が指定されていることがわかります。

volumes

データ永続化のために、MariaDB のデータ置き場である /var/lib/mysql に対して、ローカルフォルダ ./data/mariadb をマウントしています。

environment

コンテナ内の環境変数を設定しています。

entrypoint

コンテナ起動時に実行するコマンドを指定します。
今回は /docker-entrypoint-initdb.d/configure.sh を指定していますが、これは Dockerfile 内で、
事前に用意したファイルをコンテナ内部へコピーしたものを指定しています。

Redis

build

Dockerfile が置いてあるパスを指定します。
最初にお見せしたツリーを見ると Redis 用の Dockerfile の場所が指定されていることがわかります。

volumes

事前に設定してある redis.conf ファイルをコンテナ内の対象ファイルにマウントしています。

entrypoint

コンテナ起動時に実行するコマンドを指定します。
redis-server に対して、volumes でマウントしたコンフィグファイルを指定して実行しています。



MariaDB の Dockerfile

FROM mariadb:10.1.12

COPY ./docker-entrypoint-initdb.d/* /docker-entrypoint-initdb.d/

VOLUME /etc/localtime:/etc/localtime:ro

RUN sed -i -e "s/\(\[mysqld\]\)/\1\ncharacter-set-server = utf8/g" /etc/mysql/my.cnf
RUN sed -i -e "s/\(\[client\]\)/\1\ndefault-character-set = utf8/g" /etc/mysql/my.cnf
RUN sed -i -e "s/\(\[mysqldump\]\)/\1\ndefault-character-set = utf8/g" /etc/mysql/my.cnf
RUN sed -i -e "s/\(\[mysql\]\)/\1\ndefault-character-set = utf8/g" /etc/mysql/my.cnf

RUN sed -i -e "s/^#bind-addresss*=s*0.0.0.0/bind-address=0.0.0.0/" /etc/mysql/my.cnf

FROM

mariadb イメージを利用しています。バージョン指定で 10.1.12 を利用。

COPY

事前に用意した configure.sh が入っているフォルダをコンテナ内へコピーしています。

VOLUME

時計をローカルに合わせています。
最後の「ro」は ReadOnly の略で読み取り専用にしてあります。

RUN

my.cnf に対して文字列痴漢を利用して設定変更を行っています。
上の4つは文字コードの設定、下は外部からの接続を許可するバインドアドレスの設定をしています。



Laravel と Nginx

次にLaravelとNginxの設定を行います。

設定するファイルはメインの docker-compose.yml です。
中身はこんな感じになっています。

version: '2'

services:

  php:
    build:
      context: server/docker/php
    volumes:
      - "${PWD}/data/php/develop:/var/www/html"
    environment:
      DB_HOST: db
      DB_PORT: 5432
      REDIS_HOST: redis
      REDIS_PORT: 6379

  nginx:
    build:
      context: server/docker/nginx
    ports:
      - "8080:80"
    links:
      - php

  db:
    extends:
      file: storage-compose.yml
      service: db
    expose:
     - "3306"

  redis:
    extends:
      file: storage-compose.yml
      service: redis
    expose:
     - "6379"

※新しく出てきたものだけ説明します。

Nginx

ports

外部からコンテナへのポートフォワードを設定します。
8080:80 と記述すると、コンテナのIPの 8080 ポートに対してアクセスが来たら
80 ポートにポートフォワードされるようになります。

links

他のコンテナとリンクします。
docker run コマンドで -lilnk を指定するのと同じです。

DB, Redis

extends

別の yml ファイルに設定されている内容を継承します。
file に指定するのが yml フィアルの名称で、service に指定するのがコンテナ名(サービス名)です。

expose

コンテナの指定ポートを外部へ公開する設定です。
80 を指定すると、外部からコンテナの 80 ポートへアクセスが可能になります。



Laravel の Dockerfile

FROM php:fpm
WORKDIR /var/www/html

FROM

php イメージの fpm を利用しています。
nginx でPHPを利用する場合はこの fpm バージョンが必要になります。

WORKDIR

コンテナにログインした時に最初に表示されるフォルダを指定します。



Nginx の Dockerfile

FROM nginx:1.9.12
ADD conf/default.conf /etc/nginx/conf.d

FROM

nginx イメージの 1.9.12 バージョンを利用しています。

ADD

事前に用意した nginx のコンフィグファイルを対象フォルダへコピーしています。




Nginx のコンフィグファイル

NginxとPHPのコンテナが別々なので、NginxへのアクセスをPHPコンテナへ流す必要がある。
そのためのNginxのコンフィグファイルはこんな感じで設定するとうまくいった。

server {
    listen       80 default;
    server_name  localhost;
    charset utf-8;
    root /var/www/html;

    #access_log /var/www/html/access.log;
    #error_log /var/www/html/error.log;

    access_log /dev/stdout;
    error_log  /dev/stdout;

    #rewrite ^(.+)/$ $1;

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

    location ~ \.php$ {
        root /var/www/html/public;
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        #fastcgi_split_path_info ^(.+\.php)(.+)$;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
フォルダ構成

もう一度フォルダ構成を載せておきます。

.
├── data
│   └── php
├── docker-compose.yml
├── server
│   └── docker
│       ├── mariadb
│       │   ├── Dockerfile
│       │   └── docker-entrypoint-initdb.d
│       │       └── configure.sh
│       ├── nginx
│       │   ├── Dockerfile
│       │   └── conf
│       │       └── default.conf
│       ├── php
│       │   └── Dockerfile
│       └── redis
│           └── redis.conf
└── storage-compose.yml


この状態で、ルートフォルダにて下記コマンドを実行すると正常にサービスが起動するはずです。

$ docker-compose build
$ docker-compose up -d

$ docker ps -a
ONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES
01121a809ee9        laravel_db          "/docker-entrypoint-i"   2 seconds ago       Up 1 seconds        3306/tcp                        laravel_db_1
80802a0855e4        laravel_nginx       "nginx -g 'daemon off"   2 seconds ago       Up 2 seconds        443/tcp, 0.0.0.0:8080->80/tcp   laravel_nginx_1
31004578e508        laravel_php         "php-fpm"                2 seconds ago       Up 2 seconds        9000/tcp                        laravel_php_1
5b4b17aa0840        redis:3.0.5         "redis-server /usr/lo"   3 seconds ago       Up 2 seconds        6379/tcp                        laravel_redis_1

ハマった点

・NginxコンテナからPHPコンテナへルーティングするための、Nginxの設定が難しかった。
・Laravelのstorageフォルダ、bootstrapフォルダに対して、777権限を与えないと動かなかった。
 (Laravelの公式ドキュメントに権限付与してくださいってちゃんと書いてあった・・・)


まとめ

・DockerComposeは一度設定すると次回から起動・停止が非常に楽にできて便利だが、
 最初の構築するまでにひたすらつまずきポイントがあり、かなり時間を食ってしまう。
・DockerComposeで環境構築をするときは、まずひとつ1つのコンテナをしっかりと構築していくとうまくいきやすい。