docker-compose.ymlの書き方について解説してみた

## はじめに

この記事は、現在Dockerについて学習している自分が、docker-compose.ymlの書き方について、
ファイル内に記述されているコマンドの意味などをアウトプットを兼ねて解説した内容になります。

### ※お知らせ
本記事の内容をさらに詳しく解説した教材を作成しました。versionも3系に対応していますので、サンプルアプリケーションを通して動かしてみたい方は、参考にしてみてください。

[【初学者向け】RailsとMySQLをDockerizeしてみよう！](https://note.mu/ho_m_ie/n/n9f0a6756446a)

## 前回投稿したDocker関連の記事はこちら

#### 第1回Dockerハンズオン初心者・中級者編で学んだことをまとめてみた

https://qiita.com/yuta-ushijima/items/fdcaea4220e773a5ad2d

## docker-compose.ymlとは？

拡張子がYAMLの、アプリケーションを動かすための処理を記述しているファイルです。

公式サイトではComposeFileと呼ばれているので、本記事でもComposeFileと表記することにします。

[公式サイトのリファレンス](http://docs.docker.jp/compose/rails.html)から引っ張ってきたサンプルコードみると、

```yaml
version: '2'
services:
  db:
    image: mysql
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

こんな感じで記述されていますね。

前提知識がないと、なんの処理を書いているのかさっぱりだと思いますが、一つずつ用語を解説していきたいと思います。

## docker-compose.ymlに書かれている用語について

### versionって?

docker-composeで使用するバージョンを定義しています。

公式サイトによると、この記事を執筆時点(２０１８年10月13日)では、3系が最新バージョンとなっていますね。

https://docs.docker.com/compose/compose-file/

このバージョンによって、ComposeFileの書き方が異なるので、注意が必要。

ちなみに、CircleCIというCIツールは、ComposeFileのバージョンが2系以上じゃないとWarningがでます。
(将来的に1系が使われなくなる予定のため)

### Services(サービス)ってなーに？

Docker-Composeでは、アプリケーションを動かすための各要素を**Service**と読んでいます。

そのため、ComposeFileにも、`service`として、それぞれのServicesの内容をネストさせて記述していきます。

冒頭であげたサンプルコードをもう一度みてみると、`db`と`web`がServiceとして定義されていますね。

```yaml
services:
  db:
    image: mysql
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

```

`db` については、`DockerHub`にアップされている既存のDockerImageを使うことになり、Railsのようなウェブアプリケーションについては、ディレクトリを指定します。



##### dbのDockerImage指定方法(最新版を使う場合)

|MySQL|PostgreSQL|
|:--:|:--:|
|mysql:latest|postgres:latest|

ちなみに、ComposeFile内の各サービス名は、わかりやすければなんでもいいです。

なので、`db`じゃなくても`database`のように表記してもOK。

ただ、ここで定義した名前は、dockerのログに表示されるので、わかりやすい名前にした方がいいですね。

### Service設定する際の項目について

Serviceの内容の設定項目はかなりたくさんあるので、よく使うものをピックアップし、簡単な表にしてまとめてみます。

|項目|意味|リファレンスリンク
|:--:|:--:|:--:|
|restart| 実行時に再起動するかどうか | https://docs.docker.com/compose/compose-file/#restart
|environment| DBについての環境変数設定(パスワードなど) | https://docs.docker.com/compose/compose-file/#environment 
|ports| DBのDockerImageを立ち上げる際のポート番号 |https://docs.docker.com/compose/compose-file/#ports
|volumes| マウントする設定ファイルのパスを指定(mysqlのconfなど)。 |https://docs.docker.com/compose/compose-file/#short-syntax-3
|build| ComposeFileを実行し、ビルドされるときのpath | https://docs.docker.com/compose/compose-file/#build
|depends_on| Service同士の依存関係 | https://docs.docker.com/compose/compose-file/#depends_on
|entrypoint| デフォルトのentrypointを上書きする | https://docs.docker.com/compose/compose-file/#entrypoint
|driver| ボリュームに使用するドライバ(動かすための接続先)の指定。 | https://docs.docker.com/compose/compose-file/#driver

### サンプルコード

```yaml
services:
  db:
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: hogehoge
      MYSQL_PORT: 3306 # MySQLのデフォルトポート
    ports:
      - 3306:3306 # 3306のポートがきたら、3306のポートを使う
    volumes:
      - ./usr/rails/mysql/conf:/etc/mysql/conf.d:rw # Composefileからみた相対パスでmysql/confが呼び出されたら、etc/mysql/conf.dを使ってrw(読み込み・書き込み)を行う。実際は、再ビルド後も、DBの中身がリセットされないようにしてる。
      - ./mysql-datavolume:/var/lib/mysql # Composefileからみた相対パスでmysql-datavolumeが呼び出されたら、/var/lib/mysqlを指定して実行
      - "bundle:/usr/local/bundle" # Composefileからみた相対パスでbundleが呼び出されたら、ローカルのbundleファイルを指定して実行。これにより、ローカルで実行したbundle installの内容が永続化(=変更内容の適用)される。
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db # ここで指定したServiceは、`docker-compose run`した際に、指定元のServiceが実行されるよりも前に呼び出されるようになる。つまり、webというServiceよりも前に、dbというサービスが実行される。
  frontend:
    depends_on:
      - db
    ports:
      - "8200:8200"
    entrypoint: "/bin/sh -c 'npm install && npm run start'" # この記述によって、フロントエンドのフレームワーク最大の恩恵であるlive loadがdockerでも使える。ただし、このComposeFileでentrypointを指定すると、Dockerfile内のCMDやENTRYPOINTは無視されるので注意。
volumes: # このようにトップレベルでvolumesを指定すると、名前付きボリュームになる。
  bundle:
    driver: local # bundleを使う際のdriverとしてlocalを指定
  mysql-datavolume:

```

## 参考サイト

### ComposeFile version3 リファレンス(英語)
https://docs.docker.com/compose/compose-file/

### わかばちゃんによる解説書【マンガでわかるDocker】サポートページ
https://scrapbox.io/docker/