Docker Composeの仕様について混乱しがちな箇所を整理した

docker・docker composeの仕様について細かい部分を調べて理解する

# Docker compose 公式ドキュメント
https://docs.docker.com/compose/

# Docker composeとは
> Compose is a tool for defining and running multi-container Docker applications. To learn more about Compose refer to the following documentation:
https://docs.docker.com/compose/

複数コンテナから構成されるアプリケーションを構築・実行するためのツール。
一から触ってみるなら、[https://docs.docker.com/compose/gettingstarted/](https://docs.docker.com/compose/gettingstarted/)の内容を試すのが手軽。

# Docker compose CLI
`docker-compose xxx`で実行するCLIの仕様

## downとstopの違い
### down
https://docs.docker.com/compose/reference/down/

起動中のコンテナを停止・削除する。なお、デフォルトの挙動で削除されるのはdocker-compose.ymlに定義されたcontainer・networkとなる。``external``で定義したnetwork・volumeは削除対象にはならない。

また、``---volumes``指定でvolumeも削除される

### stop
https://docs.docker.com/compose/reference/stop/

起動中のコンテナを削除せずに停止する。削除していないので、`docker-compose start`で再起動する。


## multiple docker-compose file: `-f`
> Use the -f flag to specify the location of a Compose configuration file.

https://docs.docker.com/compose/reference/overview/#use--f-to-specify-name-and-path-of-one-or-more-compose-files

```
$ docker-compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db
```
複数のcomposeファイルを指定することが可能。


## up
### `-d` flag
```
    -d, --detach               Detached mode: Run containers in the background,
                               print new container names. Incompatible with
                               --abort-on-container-exit.
```
バックグラウンドでコンテナを起動。

## run
> The docker-compose run command allows you to run one-off commands for your services.

サービス定義したコンテナに対するコマンドを実行する


## bind mount

```yaml:docker-compose.yml
version: '3'
services:
    web:
        build: .
        ports:
            - "5000:5000"
        volumes:
            - .:/code
    redis:
        image: "redis:alpine"
```

https://docs.docker.com/storage/bind-mounts/

`volumes`で指定。ホストPCのディレクトリをコンテナの特定パスにマウントする。
ローカルファイル変更したら、検知され反映される。

```
web_1    |  * Detected change in '/code/app.py', reloading
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 303-274-835
```

## ps

```
-> % docker-compose ps
       Name                      Command               State           Ports
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
composetest_web_1     python app.py                    Up      0.0.0.0:5000->5000/tcp
```
実行中のプロセスを確認する。

# Docker Compose file
docker-composeの設定ファイルについてのフォーマット・各フィールド指定による効果について整理

## Version
https://docs.docker.com/compose/compose-file/compose-versioning/

compose fileのフォーマットバージョン。1・2・3とあり、2018/10/4現在は3が最新バージョン。

## Service
https://docs.docker.com/compose/compose-file/#service-configuration-reference

### argsとenvironment
> Note: If your service specifies a build option, variables defined in environment are not automatically visible during the build. Use the args sub-option of build to define build-time environment variables.

args・environment両方設定した値を環境変数にアクセスすることでコンテナ内で見ることができる。ただし、`build`オプションでイメージをビルド際に必要な環境変数がある場合は、environmentに指定しても見れないのでargsで指定する必要がある。

### ports
https://docs.docker.com/compose/compose-file/#ports
> Either specify both ports (HOST:CONTAINER), or just the container port (an ephemeral host port is chosen).

コンテナがホストに対して公開するポートを指定する。


```yaml
ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"
 - "6060:6060/udp"
```

### expose
https://docs.docker.com/compose/compose-file/#expose
> Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified.

exposeで指定したポートはlinkされたサービスからアクセス可能となる、ホストからのアクセスが可能にするための指定ではない。

```yaml
expose:
 - "3000"
 - "8000"
```

### external_links
https://docs.docker.com/compose/compose-file/#external_links
> Link to containers started outside this docker-compose.yml or even outside of Compose

docker-composeで定義したコンテナ以外のコンテナへのリンクを作成する。`CONTAINER:ALIAS`という形式で指定。

```yaml
external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql
```

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

hostnameのマッピング、コンテナ内の/etc/hostsに指定した内容が書き込まれる。

```yaml
extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"
```

### healthcheck
特定のcontainer serviceのヘルスチェックを行う設定

```
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3
```

healthcheckが通っている場合、`docker-compose ps`で表示した際の状態（State）に、`Up (health: starting) `といったように表示される。

```
-> % docker-compose ps
       Name                      Command               State           Ports
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
composetest_web_1     python app.py                    Up (health: starting)       0.0.0.0:5000->5000/tcp
```

### dns
https://docs.docker.com/compose/compose-file/#dns
> Custom DNS servers. Can be a single value or a list.

DNSサーバを指定する

```yaml
dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9
```

## Network
https://docs.docker.com/compose/compose-file/#network-configuration-reference

Networkingに関する説明は、[https://docs.docker.com/compose/networking/](https://docs.docker.com/compose/networking/)にて詳説されている。
[参考訳：Docker コンテナ・ネットワークの理解](https://qiita.com/zembutsu/items/1da05cb6a60e1c5acc25)にて日本語翻訳していただいているので、そちらを合わせてみるとより理解度が深まります。

### 本設定を省略した場合
下記のYAMLファイルのように、network設定を省略した場合。

```yaml
version: "3"
services:
  web:
    build: .
    ports:
      - "8000:8000"
  db:
    image: postgres
    ports:
      - "8001:5432"
```

- ディレクトリ名 + `_default`というネットワークが作成される。
例えば、`myapp`というディレクトリだった場合は、`myapp_default`というネットワークが作成され、各サービスは`myapp_default`にjoinする。

### すでに存在するネットワークを指定する
`external`でネットワーク名を指定することですでに存在するネットワークにjoinする。

```yaml
networks:
  default:
    external:
      name: my-pre-existing-network
```