【Docker】docker compose入門 docker-compose.ymlの基礎まとめ

備忘録として

docker-compose.ymlの書き方やその概要を一回整理しておきたいと思ったので書きます。

## 環境
・ホストOS: Windows 10 Home
・ゲストOS: wsl2 Ubuntu20.04
・Docker ver19.03
・Docker Compose ver1.25.0


## ディレクトリ構成・ファイル内容

この記事では以下のようなディレクトリ構成を例にとります。
([こちらの記事](https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4)を参考にさせていただきました。)

```yaml

.
|
├── infra
│   ├── mysql
│   │   ├── Dockerfile
│   │   └── my.cnf
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── docker-compose.yml
└── backend
    └── Laravelをインストールするディレクトリ
```

・アプリケーションサーバ
・webサーバ
・dbサーバ

の3層からなるLEMPアーキテクチャを構築するという構成です。
元記事ではPHPのフレームワークにlaravelが採用されていますが、今回はdocker-compose.ymlの知識整理が目的なので取り扱いません。



docker-compose.ymlの内容は以下の通りです。

```yml

version: "3"
services:
  app:
    build: ./infra/php
    volumes:
      - ./backend:/work
    depends_on:
      - web
  web:
    image: nginx:1.18-alpine
    ports:
      - "10080:80"
    volumes:
      - ./backend:/work
      - ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - db
    working_dir: /work

  db:
    build: ./infra/mysql
    volumes:
      - db-store:/var/lib/mysql

volumes:
  db-store:
```


docker-compose.ymlはyml(yaml)というファイル形式で書かれています。ymlについてはまずは以下のことをおさえておけばよいでしょう。


・インデントで階層構造を表現する。可読性を担保するために1つの階層はインデント2個で表現することが多い。
・行頭の - は配列を表す。同一階層にある - は同じ配列の要素になる。
・ key: value のような記述はハッシュを表現する。: の後ろに半角スペースを挟む必要がある。


## よく使うキー

###build: 
 Dockerfileからイメージを生成する際に定義します。。valueにはDockerfileのファイルパスを記述します。(相対パス、絶対パスのどちらでも問題ありません。また、docker composeは、記述されたファイルパスからDockerfileという名前のファイルを探すのでDockerfileは省略してもよいです。)


```yml
app:
  build: ./infra/php
```

今回の場合、appコンテナのもとになるイメージを ./infra/php にあるDockerfileから作成する  ということになります。


###image:
 コンテナのもとになるベースイメージを指定します。例えば公式のイメージをそのまま使う場合はbuildではなくこちらを定義します。

```yml
 web:
   image: nginx:1.18-alpine
```

ここではwebコンテナをnginxの公式イメージから生成します。

※上記より、1つのコンテナに対してbuildとimageは両立することはありません。ただし1つのdocker-compose.yml内の別のコンテナに対してこの2つを使い分けることは可能です。

###ports: 
 コンテナが公開するポートを指定します。
書式は「ホスト側のポート番号:コンテナ側のポート番号」です。
※yamlファイルではaa::bbのような書式が時刻と解釈される場合があるので、文字列を二重引用符で囲むのが無難でしょう。


```yml

web:
  image: nginx:1.18-alpine
  ports:
    - "10080:80"
```

この例ではホスト側の10080番ポートとコンテナ側の80番ポートを対応づけています。(80番ポートはnginxのデフォルトのポート番号です)

###expose:

今回は定義していませんが、コンテナのポートをホスト側に公開せず、連携する別のコンテナに対してのみ開く場合は、portsではなくexposeを使用します。


###depends_on:

コンテナの依存関係を定義します。

```yml
web:
    image: nginx:1.18-alpine
    ports:
      - "10080:80"
    volumes:
      - ./backend:/work
      - ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - db
```

上の例ではwebコンテナがdbコンテナに依存していることを定義しています。具体的には、dbコンテナが作動してからwebコンテナが作動する、という順番が定められています。

ただし、あくまでもコンテナ開始の順序が制御されるだけでありコンテナ上のdbサーバが準備できるまでwebサーバが待つというわけではありません。

そのような仕様にする場合はアプリケーション側で対策する必要があります。


###volumes


コンテナにボリュームをマウントします。聞きなれない人も多い用語だと思いますので簡単に説明すると以下のような感じです。

・ボリューム：コンテナが破棄された後もデータを保持するためのデータ格納領域。簡単に言うとコンテナ内のデータを保存するディレクトリ
・マウント：外部のファイルをlinuxOSに読み込ませること。

ざっくりというと「コンテナはデータを長期保存に向かないから外部のOSに保存しましょう」くらいの塩梅ですね。(コンテナに入ってvimでphpを編集するのは不便、という事情も大きいと思いますが...)

volumesは「マウント先のホスト側ディレクトリ：コンテナ側のディレクトリ」という書式で定義します。

```yaml
app:
  build: ./infra/php
  volumes:
    - ./backend:/work
```

ここではappコンテナ内にあるworkディレクトリ(およびその下のファイルやディレクトリ)をホスト側の./backendディレクトリにマウントしています。


##まとめ・補足

他にも定義できるキーは多数ありますが、ひとまずは基本的なものをまとめました。
まずはbuild、volumesあたりをしっかりと理解したいです。