Dockerで作るCodeIgniterローカル開発環境 docker-compose編

こんばんは。すっかり遅れてしまいましたが、
この記事は<a href="http://qiita.com/advent-calendar/2017/code_igniter" target="_blank">CodeIgniter Advent Calendar 2017</a>の11日目です。

最初はXdebugの使い方を書こうとしていたのですが、
入門前の頃の自分でも試せる様な内容にしようとしたら記事が肥大化したので、
まず前段として docker-compose の話を書きます。


## Dockerのメリット

[9日目の記事](https://qiita.com/ayato/items/25c5d06a3ba8ce78520a) でDockerを使ったローカル開発環境を作ってみましたが、これだけではDockerを使うメリットがありません。

ローカル開発環境を作るにあたってDockerを使うメリットは、雑に言うと

- 開発環境をOSごとDockerイメージという箱に詰め込んで色んな所で使える
- ホスト側の環境で必要なのはDockerだけ

という点なので、例えばXdebugの様なPHP拡張や、Node.jsの開発環境の様な「その環境を作る時点で苦労してしまう」様な物をDockerイメージに詰め込むとメリットを享受し易いです。

Vagrant / VirtualBoxでも同じメリットを得られますが、最近のクラウドサービスの動きを見ても、「色んな所で使える」というメリットはDockerの方が上です。

Macの人もWindowsの人もすぐに開発環境を整えられる！という点に留まらず、CIサービスやデプロイまで考えるのであればDockerが良いでしょう。

というわけで、Xdebugを使ってCodeIgniter製のアプリケーションをデバッグする話は丁度良い題材だったのですが、毎回ながーいdockerコマンドを打つのは筋が悪いので、docker-composeを使います。

## dockerコマンドをdocker-compose.ymlに置き換える

[9日目の記事](https://qiita.com/ayato/items/25c5d06a3ba8ce78520a) のdockerコマンドをまた見てみます。

```
$ cd ~/Desktop/CodeIgniter-3.1.6

$ docker run -p 80:80 -d -v ${PWD}:/var/www/html/ --name codeigniter-local php:7.2-apache
```

このコマンドでは、

- `php:7.2-apache` のDockerイメージを基に、 `codeigniter-local` というDockerコンテナを起動
    - `-d` オプションでバックグラウンド起動
- コンテナの80番ポートと、ホスト（macOS等）の80番ポートを接続
- 今居るホスト側の `~/Desktop/CodeIgniter-3.1.6` とコンテナ側の `/var/www/html` を共有

という事をしています。
同等の内容をdocker-composeの設定ファイルである `docker-compose.yml` に書いてみます。

```yaml
version: '2'

services:
  dev:
    container_name: "codeigniter-local"
    image: php:7.2-apache
    working_dir: /var/www/html
    volumes:
      - ./:/var/www/html
    ports:
      - "80:80"
```

カンタンな内容ですが、上から順に解説すると

- docker-composeの設定ファイルとしては version 2 を指定
    - 2017年12月現在の最新は 3 ですが、そんなに差も無いですし、クラウドサービスで使い回し易いのは現状 2 の方なのでこちらを採用
- 立ち上げるコンテナをdocker-composeから操作する時のサービス名として `dev` を指定
- 立ち上げるコンテナ名はdockerコマンドの時と同じく `codeigniter-local`
    - この2つは好きな物でかまいません
- コンテナの基になるdockerイメージも同じく [php:7.2-apache](https://hub.docker.com/_/php/)
- コンテナの中に入った時、最初に居るディレクトリを `working_dir` で指定
    - dockerコマンドの時は特に指定してませんでした
- ホスト側とコンテナ側で共有する部分を `volumes` で指定
    - ホスト側のディレクトリを、dockerコマンドの時は `${PWD}` と環境変数を使って指定してましたが、今度は `docker-compose.yml` からの相対パスで指定
- コンテナの80番ポートと、ホスト（macOS等）の80番ポートを接続

という感じです。

これで `-d` オプションでコンテナをバックグラウンド起動する所以外は `docker-compose.yml` にかけました。

## docker-composeコマンドでコンテナを使う

この `docker-compose.yml` を設置して docker-compose コマンドを叩くだけです。

```
$ cd ~/Desktop/CodeIgniter-3.1.6

$ vim ./docker-compose.yml

$ docker-compose up -d
```

ここで `-d` オプションを付けてコンテナをバックグラウンド起動しています。
コンテナが立ち上がれば、前回と同様に `docker ps` コマンドを叩くか、 `docker-compose ps` コマンドでも確認が出来ます。

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
2712eb546422        php:7.2-apache      "docker-php-entryp..."   25 hours ago        Up 25 hours         0.0.0.0:80->80/tcp   codeigniter-local

$ docker-compose ps
      Name                     Command               State         Ports
-------------------------------------------------------------------------------
codeigniter-local   docker-php-entrypoint apac ...   Up      0.0.0.0:80->80/tcp
```

コンテナ立ち上げたときに `codeigniter-local` という名前を付けたので、それを使ってコマンドを叩きます。
`dev` というサービス名から `docker-compose` コマンドを叩いても良いです。

|操作|dockerコマンド|docker-composeコマンド|
|---|---|---|
|コンテナ停止|`docker stop codeingiter-local`|`docker-compose stop dev`|
|コンテナ起動|`docker start codeingiter-local`|`docker-compose start dev`|
|ログ確認|`docker logs codeigniter-local`|`docker-compose logs dev`|
|ログ監視|`docker logs -tf codeigniter-local`|`docker-compose logs -tf dev`|
|コンテナ削除|`docker rm codeigniter-local`<br>（停止している時のみ）|`docker-compose down`<br>（停止していなくても可能）|

1点注意したいのが、docker-composeコマンドで起動したコンテナの設定を変えようと思って `docker-compose.yml` を編集するのであれば、その前にそのコンテナを破棄しておかないといけません。

docker-composeコマンドは `docker-compose.yml` の内容を見て動作するので、起動している最中に設定を書換えてしまうと、「あれ、起動した時と話が違うぞ」となってしまい、コケる場合があります。

dockerコンテナは気軽に作って壊しが出来るので、調べながら試してみてください。

## おわりに

CodeIgniterの話まで行き着きませんでしたね。
なが～くなった記事の前半なので、ご容赦下さい。

docker-composeは本来、複数のコンテナを一度にコントロールする為のツールなので、
今回のように1つのコンテナを操作するだけであれば、別に必須ではありません。

ですが、すぐに履歴の彼方に消えてしまうコマンドではなく、 `docker-compose.yml` にコンテナの設定を書いておけば、未来の自分の助けになります。
僕はそう思ってコンテナが1つのときでも `docker-compose.yml` を書くことが多いです。

次回はこの `docker-compose.yml` を書換えて、Xdebugを動かす所までやります。

## おまけ

僕はコマンドで `docker-compose` と打つのが長くてイヤなので、[Oh-my-zshのdocker-composeプラグイン](https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/docker-compose) を使ってます。

```zsh
zplug "plugins/docker-compose", from:oh-my-zsh
```

`docker-compose` が `dco` と短く打てたり、コンテナ名/サービス名の補完が効くので重宝しています。