docker-compose.ymlでよく見るワードについてまとめてみた

## はじめに
Docker-compose.ymlについて理解できた部分が少し増えてきたので、アウトプットかつ備忘録としてこの記事を書きました。この記事を読む際は、前提知識としてリンク先の内容(①~⑥)は理解しておいた方が良いと思います。私もお世話になりました。
- [Docker超入門①〜Dockerってなに？〜【初心者向け】](
https://datawokagaku.com/whatisdocker/) 

広く浅く知りたいという方向け(主に私のような初学者)に導入記事として書いたものなので、この記事を読み深く知りたくなった箇所は各自公式ドキュメントなどを読んでインプットしてください！

間違っている箇所があればご指摘のほどよろしくお願い致します。

##説明するdocker-compose.yml 　

```docker-compose.yml

version: “3”

services:
  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - “8000:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      - db

  db:
    image: mysql:8.0.21
    ports:
      - "53306:3306"
    volumes:
      - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./docker/db/mysql_data:/var/lib/mysql
    env_file:
      - ./docker/db/db-variables.env
```

app:の詳細な設定はDockerfileに記述していますがその説明は省きます。
では１つずつ見ていきましょう！

##version

docker-composeで使用するバージョンを定義しています。
このバージョンによって、**ComposeFileの書き方が異なる**ので、注意が必要です。
特にこだわりがなければ**最新のもの**を記述するようにしましょう。

##services

「サービス」は、起動するコンテナの設定の定義です。

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

サービス定義には、そのサービスのために起動された各コンテナに適用される設定が含まれていて、それぞれのServicesの内容をネストさせて記述していきます。

app:,db:と書かれている箇所は、アプリケーションを動かすために使っている各要素の名前を書きます。ちなみに、**app:やdb:のように定義した名前はdockerのログに表示されるので、誰が見てもわかりやすい名前にした方が良いと思います。**

##image

コンテナを起動するimageをDockerHubから指定します。リポジトリ/タグまたは部分的なimageIDを指定します。

書き方としては、以下のように書く。

|MySQL(最新版)の場合|バージョンを指定する場合|
|-------|---------|
|mysql:latest   |mysql:5.7|

##build

ビルド時に適用される設定オプションで、ビルドコンテキストを指定します。

簡単に説明すると、指定したディレクトリにあるdockerfileからimage作成するように指示をする感じです。

``ビルドコンテキスト``とは、docker buildを実行する際の現在の作業ディレクトリのことをビルドコンテキスト(build context)と呼びます。

buildコマンド実行時に設定として読み込むDockerfileは、デフォルトではビルドコンテキスト上のDockerfiileが読み込まれるようになっているので、ビルドコンテキストにDockerfileを置いておく必要があります。

##context

Dockerfile を含むディレクトリへのパス。

与えられた値が相対パスの場合は、Composefileの場所からの相対パスとして解釈されます。

##dockerfile

代替のDockerfileです。

Composeは代替ファイルを使ってビルドします。ビルドパスも指定する必要があります。ここで元となるdockerfileを指定する。

##ports

ホスト側の値がキーであり、コンテナ側の値はバリューとなります。
ホスト側のポートとコンテナ側のポート[HOST:CONTAINER]するか、コンテナ側のポートのみ指定します。※この際、ホスト側のポートはランダムに選ばれます

書き方としては

`xx`形式
`xx:yy`形式
`xx:yy:zz`形式　があります。

portsはホスト側のポートとコンテナ側のポートをマッピングするためのセクションですが、書き方の違いによって下記の通り異なった挙動をとります。

`xx`形式はコンテナ側のポート番号のみを指定する書式であり、指定されたコンテナ側ポートがホスト側のランダムなポートとマッピングされます。

`xx:yy`形式はホスト側のポートとコンテナ側のポートを指定する書式です。xxがホスト側ポート、yyがコンテナ側ポートとなり、ホスト側のxx番ポートとコンテナ側のyy番ポートがマッピングされます。

`xx:yy:zz`形式は、xxが ホスト側のポートへの接続を許可する接続元IP、yyがホスト側のポート、zzがコンテナ側のポートとなります。ホスト側のyy番ポートへのアクセスはIPxxからの接続時のみ許可され、コンテナ側のzz番ポートとマッピングされます。

*注意*
HOST:CONTAINER形式でポートをマッピングする場合、60よりも低いコンテナポートを使うと、YAMLはxx:yy形式の数値をベース60の値として解析するため、誤った結果を出すかもしれません。この理由から、**ポートマッピングを常に明示的に文字列として指定することをお勧めします。**

とりあえず"8000:80”のように文字列で書きましょう。

##volumes

ホスト側のディレクトリや名前付きボリュームをコンテナ側へマウントしたい時に記述します。
``マウント``とは、コンテナの外にあるデータを、コンテナの中で利用できる状態にすることを意味します。
今回はホスト側の ./src ディレクトリをappサービスのコンテナ内 /var/www/html へマウントしてます。

volumesを使うことで

* コンテナを削除してもコンテナ内のデータを永久的に残すことができる
* コンテナ間でデータを共有できる

などの利点があります。

``注意``
コンテナを削除してもvolumeは残り続けるので、``$ docker-compose down -v``　などで削除する必要がある点に注意してください。


##depends_on

サービス同士の依存関係を設定することができ、コンテナの起動タイミングを変更することができます。

上記の例では、app:のdepends_onでdbを指定している為、dbがappよりも先に起動するようになる。
この記述に従ってdocker-compose upは、依存関係順にサービスを起動します。

``注意``
depends_onは立ち上げコマンドを実行する順番を規定するだけであり、dbが起動完了してからwebを実行するということではありません。

このことが原因でdocker-compose upが失敗する場合があるので、その場合は``entrypoint:``で起動待ちをする、``shell script``を実行するなどして対処します。

``追記``
depends_onはappを起動する前にdbが "準備ができた "状態になるのを待たず、それらが起動されるまで待つだけです。サービスの準備が整うのを待つ必要がある場合、https://docs.docker.com/compose/startup-order/ を参照してください。

##env_file

.envファイルから環境変数を追加します。

docker-compose -f FILE で Composeファイルを指定している場合、env_file のパスはファイルがあるディレクトリからの相対パスになります。
今回は、.envファイルに環境変数を設定しています。(env_fileは自分で手を動かして環境変数を設定しないと理解しにくいと思うので流し読みしてください)

##終わりに

分からないことは基本的に公式ドキュメントを読めば答えが出てくるので、この記事を読み理解できない箇所や気になった箇所があれば公式ドキュメントを読んでみてください。

少しでもお役に立てれば幸いです。

##参考文献

- [docker docs](https://docs.docker.com/reference/)