【爆速】 15分で CakePHP3 実行環境を簡単に構築する by Docker

Dockerを用いて CakePHP3 の実行環境を簡単に構築したいと思います。

※ CakePHP3 はウェブ開発を簡単に行うためのフレームワークです。
詳しくは公式ドキュメントをご覧ください。
https://book.cakephp.org/3.0/en/index.html


今回は、こちらの記事 (https://qiita.com/motty93/items/ccdaf130443a8334bd93) を参考にさせていただきました。

非常に良い記事でCakePHP3の実行環境を作成できたのですが、僕が一部詰まってしまった部分 (intlのインストール) があったので、その部分もスムーズに進められるようにアレンジさせていただきました。

github上で公開しています。（実は自作のリポジトリはこれが初めてです。。。）
https://github.com/km42428/docker-cakephp3-template.git

リポジトリのクローンは、以下のコマンドでできます。

```bash
git clone https://github.com/km42428/docker-cakephp3-template.git
```

# 動作環境

* Docker 18.06.1-ce
* Docker Compose 1.22.0
* Docker Machine 0.15.0

# 実行手順
## Dockerのインストール
- Macの方
Mac で Dockerを使えるように、 Docker for Mac というものが用意されています。
インストール手順は以下の記事で説明されているので参考にして下さい！
https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81

- Ubuntuの方
公式のDockerをインストールできます。
インストール手順は以下の記事で説明されているので参考にして下さい！
https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d

- Windowsの方
Windows で Dockerを使えるように、 Docker for Windows というものが用意されています。
公式ドキュメントをご覧ください。
http://docs.docker.jp/windows/step_one.html
※Windowsの場合、以下の手順が正常に動かない場合がありますので、参考程度にご覧ください。

Dockerをインストールできたら、
以下のコマンドで正しくインストールされているか確認して下さい。
僕の場合は以下のような出力になりました。

```bash
$ docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:21:31 2018
 OS/Arch:           darwin/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:29:02 2018
  OS/Arch:          linux/amd64
  Experimental:     true
```

## Docker Composeのインストール

Docker Composeのインストールについては、以下の記事を参考にしてください。
https://qiita.com/zembutsu/items/dd2209a663cae37dfa81

Docker Composeをインストールできたら、
以下のコマンドで正しくインストールされているか確認して下さい。
僕の場合は以下のような出力になりました。

```bash

$ docker-compose --version
docker-compose version 1.22.0, build f46880f
```

## 初期設定 (CakePHP3のプロジェクト作成)
CakePHP3はプロジェクト毎に実行環境を持つので、はじめにプロジェクトを作成します。
別のプロジェクトを作成する場合も、同様の手順を踏めばOKです。

環境は以下のdocker-compose.ymlに記述しています。

```docker-compse.yml

version: '2'
services:
  mysql:
    restart: always
    build: ./data/mysql/
    volumes:
      - "./data/mysql/db:/var/lib/mysql"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: my_app
      MYSQL_PASSWORD: secret
      MYSQL_DATABASE: my_app
      TZ: "Asia/Tokyo"
    ports:
      - "3307:3306" # 3306ポートにするとローカルのMySQLと被りうるのでわざとポートをずらしています。
  nginx:
    restart: always
    image: "nginx:mainline-alpine"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./data/nginx/conf:/etc/nginx/"
      - "./data/htdocs:/var/www/html"
    environment:
      TZ: "Asia/Tokyo"
    depends_on:
      - phpfpm
    links:
      - phpfpm
  phpfpm:
    restart: always
    build: ./data/phpfpm/
    environment:
      TZ: "Asia/Tokyo"
    volumes:
      - "./data/htdocs:/var/www/html"
    depends_on:
      - mysql
    links:
      - mysql
  host:
    build: ./data/htdocs
    environment:
      TZ: "Asia/Tokyo"
      PRJ: "sample"
    volumes:
      - "./data/htdocs:/root"
    ports:
      - "8765:80"
    depends_on:
      - mysql
      - phpfpm
    links:
      - mysql
      - phpfpm
```

`nginx` と `phpfpm` サービスについては、以下の記事で説明されています。
https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc

`host` はCakePHP3を実際に起動するサービスです。
environmentのPRJは起動するプロジェクト名を示しています。(今回は `sample` という名前にしています)
※別プロジェクトを作成した際はこちらを変更してください。

初めに以下を実行してDockerのイメージを作成します。
イメージの作成は 2,3分ほどかかります。

```bash
$ docker-compose build
```

正常に実行できれば以下のイメージができます。
nginxに関しては、公式のイメージを引っ張ってくるので、この時点では作成されていません。

```bash
$ docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED              SIZE
docker-cakephp3-template_host      latest              2a706bb934fa        44 seconds ago       465MB
docker-cakephp3-template_phpfpm    latest              b5019579816a        About a minute ago   114MB
docker-cakephp3-template_mysql     latest              e2f4e50d4453        2 minutes ago        372MB
```

次にphpfpmのコンテナを作成した上で、プロジェクトを作成します。
今回は `sample` という名前のプロジェクトを作成してみます。
（以下の手順はあまりスマートではないかもしれません。もっと良い方法があれば教えていただきたいです！）

- docker-compose build で作成したイメージから、バックグラウンドでコンテナを立ち上げます。

```bash
$ docker-compose up -d
```

- 作成されているコンテナを確認します。 (現時点ではプロジェクトが存在しないことによるエラーのため、`host` のコンテナは生成されていません。)

```bash
$ docker ps
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                                      NAMES
5dc8199c222e        nginx:mainline-alpine             "nginx -g 'daemon of…"   5 seconds ago       Up 3 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   docker-cakephp3-template_nginx_1
c9ae28fe914e        docker-cakephp3-template_phpfpm   "docker-php-entrypoi…"   6 seconds ago       Up 4 seconds        9000/tcp                                   docker-cakephp3-template_phpfpm_1
c8aba730acf9        docker-cakephp3-template_mysql    "docker-entrypoint.s…"   6 seconds ago       Up 5 seconds        33060/tcp, 0.0.0.0:3307->3306/tcp          docker-cakephp3-template_mysql_1
```

- phpfpmコンテナに入り、ターミナルを立ち上げます。 (上記で取得した phpfpm の container id を使用します。今回のidは `c9ae28fe914e` です)

```bash
$ docker exec -it c9ae28fe914e /bin/sh
```

※ ちなみにコンテナに入る場合は コンテナ名を指定してもOKです。

```bash
$ docker exec -it docker-cakephp3-template_phpfpm_1 /bin/sh
```


- composerのinstallerを取得します。

```

/var/www/html # curl -s https://getcomposer.org/installer | php
```

- sampleプロジェクトを作成します。(installで 2,3分ほどかかります。)

```

/var/www/html # php composer.phar create-project --prefer-dist cakephp/app sample
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Installing cakephp/app (3.6.5)
  - Installing cakephp/app (3.6.5): Downloading (100%)
Created project in sample
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 47 installs, 0 updates, 0 removals
  - Installing cakephp/plugin-installer (1.1.0): Downloading (100%)
  - Installing psr/http-message (1.0.1): Downloading (100%)
  - Installing zendframework/zend-diactoros (1.8.6): Downloading (100%)
  - Installing psr/log (1.0.2): Downloading (100%)
  - Installing aura/intl (3.0.0): Downloading (100%)
  - Installing cakephp/chronos (1.2.2): Downloading (100%)
  - Installing cakephp/cakephp (3.6.11): Downloading (100%)
  - Installing symfony/polyfill-ctype (v1.9.0): Downloading (100%)
  - Installing symfony/yaml (v4.1.4): Downloading (100%)
  - Installing symfony/polyfill-mbstring (v1.9.0): Downloading (100%)
  - Installing symfony/console (v4.1.4): Downloading (100%)
  - Installing symfony/filesystem (v4.1.4): Downloading (100%)
  - Installing symfony/config (v4.1.4): Downloading (100%)
  - Installing robmorgan/phinx (0.10.6): Downloading (100%)
  - Installing cakephp/migrations (2.0.0): Downloading (100%)
  - Installing m1/env (2.1.2): Downloading (100%)
  - Installing josegonzalez/dotenv (3.2.0): Downloading (100%)
  - Installing mobiledetect/mobiledetectlib (2.8.33): Downloading (100%)
  - Installing twig/twig (v1.35.4): Downloading (100%)
  - Installing umpirsky/twig-php-function (v0.1): Downloading (100%)
  - Installing jasny/twig-extensions (v1.2.0): Downloading (100%)
  - Installing asm89/twig-cache-extension (1.3.2): Downloading (100%)
  - Installing aptoma/twig-markdown (2.0.0): Downloading (100%)
  - Installing ajgl/breakpoint-twig-extension (0.3.1): Downloading (100%)
  - Installing wyrihaximus/twig-view (4.3.5): Downloading (100%)
  - Installing cakephp/bake (1.8.4): Downloading (100%)
  - Installing squizlabs/php_codesniffer (3.3.1): Downloading (100%)
  - Installing cakephp/cakephp-codesniffer (3.0.5): Downloading (100%)
  - Installing jdorn/sql-formatter (v1.2.17): Downloading (100%)
  - Installing symfony/process (v4.1.4): Downloading (100%)
  - Installing symfony/finder (v4.1.4): Downloading (100%)
  - Installing seld/phar-utils (1.0.1): Downloading (100%)
  - Installing seld/jsonlint (1.7.1): Downloading (100%)
  - Installing justinrainbow/json-schema (5.2.7): Downloading (100%)
  - Installing composer/xdebug-handler (1.3.0): Downloading (100%)
  - Installing composer/spdx-licenses (1.4.0): Downloading (100%)
  - Installing composer/semver (1.4.2): Downloading (100%)
  - Installing composer/ca-bundle (1.1.2): Downloading (100%)
  - Installing composer/composer (1.7.2): Downloading (100%)
  - Installing cakephp/debug_kit (3.16.4): Downloading (100%)
  - Installing symfony/polyfill-php72 (v1.9.0): Downloading (100%)
  - Installing symfony/var-dumper (v4.1.4): Downloading (100%)
  - Installing nikic/php-parser (v4.0.3): Downloading (100%)
  - Installing jakub-onderka/php-console-color (0.1): Downloading (100%)
  - Installing jakub-onderka/php-console-highlighter (v0.3.2): Downloading (100%)
  - Installing dnoegel/php-xdg-base-dir (0.1): Downloading (100%)
  - Installing psy/psysh (v0.9.8): Downloading (100%)
cakephp/app suggests installing markstory/asset_compress (An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.)
cakephp/app suggests installing dereuromark/cakephp-ide-helper (After baking your code, this keeps your annotations in sync with the code evolving from there on for maximum IDE and PHPStan compatibility.)
cakephp/app suggests installing phpunit/phpunit (Allows automated tests to be run without system-wide install.)
cakephp/cakephp suggests installing lib-ICU (The intl PHP library, to use Text::transliterate() or Text::slug())
symfony/console suggests installing psr/log-implementation (For using the console logger)
symfony/console suggests installing symfony/event-dispatcher
symfony/console suggests installing symfony/lock
m1/env suggests installing m1/vars (For loading of configs)
asm89/twig-cache-extension suggests installing psr/cache-implementation (To make use of PSR-6 cache implementation via PsrCacheAdapter.)
aptoma/twig-markdown suggests installing michelf/php-markdown (Original Markdown engine with MarkdownExtra.)
aptoma/twig-markdown suggests installing knplabs/github-api (Needed for using GitHub's Markdown engine provided through their API.)
ajgl/breakpoint-twig-extension suggests installing ext-xdebug (The Xdebug extension is required for the breakpoint to work)
ajgl/breakpoint-twig-extension suggests installing symfony/framework-bundle (The framework bundle to integrate the extension into Symfony)
ajgl/breakpoint-twig-extension suggests installing symfony/twig-bundle (The twig bundle to integrate the extension into Symfony)
composer/composer suggests installing ext-zip (Enabling the zip extension allows you to unzip archives)
psy/psysh suggests installing ext-pcntl (Enabling the PCNTL extension makes PsySH a lot happier :))
psy/psysh suggests installing ext-pdo-sqlite (The doc command requires SQLite to work.)
psy/psysh suggests installing hoa/console (A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit.)
Writing lock file
Generating autoload files
> Cake\Composer\Installer\PluginInstaller::postAutoloadDump
> App\Console\Installer::postInstall
Created `config/app.php` file
Created `/var/www/html/sample/tmp/cache/views` directory
Set Folder Permissions ? (Default to Y) [Y,n]? Y # ここではYを選択してください。
Permissions set on /var/www/html/sample/tmp/cache/views
Updated Security.salt value in config/app.php
```

- コンテナを抜けます。

```
/var/www/html # exit
```

以上が完了すると `data/htdocs/` の配下に `sample` フォルダが作成されるはずです。
これでプロジェクトの雛形が完成しました。

作成された `sample` プロジェクトで `mysql` に接続するためにファイルを一部書き換えます。

以下のファイルの `250行目付近` の `host` を `localhost` から `mysql` に書き換えます。
これは、ローカルの `mysql` ではなく、docker-compose.yml で定義した `mysqlサービス` に接続するためです。

```data/htdocs/sample/config/app.php
    'Datasources' => [
        'default' => [
            'className' => Connection::class,
            'driver' => Mysql::class,
            'persistent' => false,
            'host' => 'mysql', # この行を localhostからmysqlに変更してください。
```

## 実行環境の立ち上げ
前の手順で作成した `sample` プロジェクトがある前提で説明します。
docker-compose.yml の `host` サービスの環境変数で、 `sample` プロジェクトが指定されていることを確認します。

```docker-compose.yml

version: '2'
services:
  ..(省略)..
  host:
    build: ./data/htdocs
    environment:
      TZ: "Asia/Tokyo"
      PRJ: "sample"　# ここがプロジェクト名です。別名にする場合は適宜書き換えてください。
    ..(省略)..
```


以下のコマンドで、起動します。

```bash
$ docker-compose up -d
```

正常に実行されればローカルで動作を確認できます。
http://localhost:8765

以下のように表示されれば成功です。

<img width="1602" alt="スクリーンショット 2018-09-18 3.26.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/291512/b748a76d-e2fa-e56b-0cf1-f938b6194a30.png">

特に、 `Database` が正常に接続されているかご確認ください。
以下のようになっていればOKです。

```
CakePHP is able to connect to the database.
```

もしエラーが出ていた場合は、 `data/htdocs/sample/config/app.php` を修正してください。

## 実行環境の終了

以下のコマンドでコンテナを削除します。

```bash
$ docker-compose down 
```

以上です。
もし正常に動作しなかった場合や、もっとこうしたほうが良いなどあれば、
どしどしコメントください。

よいCakePHP3ライフを！