docker-composeでEC-CUBE4の開発環境構築

# 方針

- dockerやdocker-composeのHow Toはここでは扱わない。
- カレントディレクトリをそのままマウントする。
- リモートデバッグを有効にする。
- HTTPポートとリモートデバッグポートは変更可能とする。
- ビルトインサーバーは今回の用途では使えない。
    - docker-composeで使う.envとEC-CUBEの.envが重複する。
    - EC-CUBEの.envを回避するために$_SERVERに値をセットする必要がある。
    - ビルトインサーバーで$_SERVERに値をセットする方法がなく、ApacheのSetEnvディレクティブを使う必要がある。
        - もし方法があったら教えて下さい。
- そのままだとログ等がroot権限で作られるため、コンテナ側のwww-dataのUIDをホスト側ユーザーのUIDと揃える。
    - ホスト側ユーザーのUIDがコンテナ側に既に存在するケースは想定していない点に注意。
- 動作確認環境: Linux Mint 18.1

# 構築

## TL;DR

完成品: https://github.com/izayoi256/ec-cube/tree/4.0.0-docker-compose

## まずはpull

2018/10/17時点で最新の4.0.0を利用。

``` sh
$ git clone -b 4.0.0 https://github.com/EC-CUBE/ec-cube.git
$ cd ec-cube
```

## ファイルを追加

``` Dockerfile:docker/ec-cube/Dockerfile
FROM php:7.1-apache

RUN set -x \
    # 高速化のためaptリポジトリを変更
    && sed -i.bak -e "s%http://deb.debian.org/debian%http://ftp.riken.jp/pub/Linux/debian/debian%g" /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
        sudo \
        git \
        libxml2-dev \
        unzip \
        wget \
        zlib1g-dev \
        iproute \
        libsqlite3-dev \
        libpq-dev \
        libicu-dev \
        gnupg2 \
    && wget -qO- https://deb.nodesource.com/setup_10.x | bash - \
    && apt-get install -y --no-install-recommends \
        nodejs \
    && docker-php-ext-install \
        intl \
        mbstring \
        pdo \
        pdo_sqlite \
        pdo_mysql \
        pdo_pgsql \
        soap \
        xml \
        zip \
    && pecl install xdebug \
    && pecl install apcu \
    && docker-php-ext-enable \
        xdebug \
        apcu \
        opcache \
    && a2enmod rewrite \
    && apt-get clean \
    && rm -rf /tmp/*

RUN curl -sS https://getcomposer.org/installer \
    |  php -- \
        --filename=composer \
        --install-dir=/usr/local/bin \
    # composerの高速化
    && COMPOSER_ALLOW_SUPERUSER=1 composer global require --optimize-autoloader "hirak/prestissimo" \
    && chown www-data /var/www \
    && chmod g+s /var/www/html

COPY ./my.ini /usr/local/etc/php/conf.d/my.ini
COPY ./my.conf /etc/apache2/conf-available/my.conf
COPY ./entrypoint.sh /entrypoint.sh

RUN a2enconf my

ENTRYPOINT ["/entrypoint.sh"]
CMD ["apache2-foreground"]
```

``` ini:docker/ec-cube/my.ini
# phpの設定を記載
# 今回はとりあえずxdebugとopcache関連
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.profiler_enable=0

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=64
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=16000
opcache.revalidate_freq=0
opcache.fast_shutdown=1
```

``` conf:docker/ec-cube/my.conf
# ApacheのWarning対策
ServerName localhost:80

# PHP用の環境変数をサーバー変数に渡すための設定
PassEnv APP_ENV
PassEnv APP_DEBUG
PassEnv DATABASE_URL
PassEnv DATABASE_SERVER_VERSION
PassEnv MAILER_URL
PassEnv ECCUBE_AUTH_MAGIC
PassEnv TRUSTED_PROXIES
PassEnv TRUSTED_HOSTS
PassEnv ECCUBE_LOCALE
PassEnv ECCUBE_TIMEZONE
PassEnv ECCUBE_CURRENCY
PassEnv ECCUBE_ADMIN_ROUTE
PassEnv ECCUBE_USER_DATA_ROUTE
PassEnv ECCUBE_ADMIN_ALLOW_HOSTS
PassEnv ECCUBE_FORCE_SSL
PassEnv ECCUBE_TEMPLATE_CODE
PassEnv ECCUBE_COOKIE_NAME
PassEnv ECCUBE_COOKIE_PATH
PassEnv ECCUBE_COOKIE_LIFETIME
PassEnv ECCUBE_GC_MAXLIFETIME
```

``` sh:docker/ec-cube/entrypoint.sh
#!/bin/sh
set -e

# www-dataのUIDを変更する
if [ -n "${HOST_UID}" -a "${HOST_UID}" != "$(id -u www-data)" ]; then
    usermod -u "${HOST_UID}" www-data
fi

# リモートデバッグの設定は環境変数だけでは対応できないため動的に追記
xdebug=$(cat << EOS
xdebug.remote_host=$(ip route | awk 'NR==1 {print $3}')
xdebug.remote_port=${XDEBUG_PORT}
EOS
)
echo "${xdebug}" >> /usr/local/etc/php/conf.d/my.ini

if [ -e "composer.json" ]; then
    sudo -u www-data composer install
fi

if [ -e "package.json" ]; then
    sudo -u www-data npm install
fi

if [ "${1#-}" != "$1" ]; then
	set -- apache2-foreground "$@"
fi

exec "$@"
```

``` yml:docker-compose.yml
version: "3"
services:
  ec-cube:
    build: ./docker/ec-cube
    volumes:
      - .:/var/www/html
    environment:
      - HOST_UID
      - TZ=${TZ:-Asia/Tokyo}
      - XDEBUG_PORT=${ECCUBE_XDEBUG_PORT:-9000}
      - APP_ENV=${ECCUBE_APP_ENV:-prod}
      - APP_DEBUG=${ECCUBE_APP_DEBUG:-1}
      - DATABASE_URL=${ECCUBE_DATABASE_URL:-sqlite:///%kernel.project_dir%/var/eccube.db}
      - DATABASE_SERVER_VERSION=${ECCUBE_DATABASE_SERVER_VERSION:-3}
      - MAILER_URL=${ECCUBE_MAILER_URL:-null://localhost}
      - ECCUBE_AUTH_MAGIC=${ECCUBE_AUTH_MAGIC:-supersecureauthmagic}
      - TRUSTED_PROXIES=${ECCUBE_TRUSTED_PROXIES:-}
      - TRUSTED_HOSTS=${ECCUBE_TRUSTED_HOSTS:-}
      - ECCUBE_LOCALE=${ECCUBE_LOCALE:-ja}
      - ECCUBE_TIMEZONE=${ECCUBE_TIMEZONE:-Asia/Tokyo}
      - ECCUBE_CURRENCY=${ECCUBE_CURRENCY:-JPY}
      - ECCUBE_ADMIN_ROUTE=${ECCUBE_ADMIN_ROUTE:-admin}
      - ECCUBE_USER_DATA_ROUTE=${ECCUBE_USER_DATA_ROUTE:-user_data}
      - ECCUBE_ADMIN_ALLOW_HOSTS=${ECCUBE_ADMIN_ALLOW_HOSTS:-[]}
      - ECCUBE_FORCE_SSL=${ECCUBE_FORCE_SSL:-false}
      - ECCUBE_TEMPLATE_CODE=${ECCUBE_TEMPLATE_CODE:-default}
      - ECCUBE_COOKIE_NAME=${ECCUBE_COOKIE_NAME:-eccube}
      - ECCUBE_COOKIE_PATH=${ECCUBE_COOKIE_PATH:-/}
      - ECCUBE_COOKIE_LIFETIME=${ECCUBE_COOKIE_LIFETIME:-0}
      - ECCUBE_GC_MAXLIFETIME=${ECCUBE_GC_MAXLIFETIME:-1440}
    ports:
      - "${ECCUBE_HTTP_PORT:-8080}:80"
```

``` env:.default.env
# EC-CUBEのHTTPポート番号
#ECCUBE_HTTP_PORT=

# EC-CUBEのxdebug.remote_port
#ECCUBE_XDEBUG_PORT=

# EC-CUBEの設定
#ECCUBE_APP_ENV=
#ECCUBE_APP_DEBUG=
#ECCUBE_DATABASE_URL=
#ECCUBE_DATABASE_SERVER_VERSION=
#ECCUBE_MAILER_URL=
#ECCUBE_AUTH_MAGIC=
#ECCUBE_TRUSTED_PROXIES=
#ECCUBE_TRUSTED_HOSTS=
#ECCUBE_LOCALE=
#ECCUBE_TIMEZONE=
#ECCUBE_CURRENCY=
#ECCUBE_ADMIN_ROUTE=
#ECCUBE_USER_DATA_ROUTE=
#ECCUBE_ADMIN_ALLOW_HOSTS=
#ECCUBE_FORCE_SSL=
#ECCUBE_TEMPLATE_CODE=
#ECCUBE_COOKIE_NAME=
#ECCUBE_COOKIE_PATH=
#ECCUBE_COOKIE_LIFETIME=
#ECCUBE_GC_MAXLIFETIME=

# タイムゾーン
#TZ=
```

# 実行

docker-compose.ymlに記述されているデフォルトの環境変数から変更したい場合は.envファイルに記載する。
(変更不要であればコピーしなくてもよい)

``` sh
$ cp .default.env .env
$ vim .env
```

HOST_UIDにホストのUIDを指定してコンテナを起動する。

``` sh
$ HOST_UID=$(id -u) docker-compose up -d
```

# 動作確認

``` sh
$ curl -D - -s -o /dev/null http://localhost:8080/
HTTP/1.1 200 OK
Date: Wed, 17 Oct 2018 09:29:52 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/7.1.23
Set-Cookie: eccube=cf2898f013116d20403f72188cf10158; path=/; HttpOnly
Cache-Control: max-age=0, must-revalidate, private
Set-Cookie: device_view=full; expires=Sat, 17-Nov-2018 09:29:55 GMT; Max-Age=2678400; path=/; httponly
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
```