DockerのきほんとDocker Composeについて

## はじめに
環境構築でお世話になるDocker Compose。定義ファイルさえあれば、いくつかコマンド打つだけで環境構築ができてしまい、とても便利ですよね。
今回はDockerとComposeの理解を深めるため、Dockerの基本を確認しつつ、Docker Composeの定義ファイルの中身を初学者なりに読み解いてみたいと思います。

## そもそもDockerとは

[公式リファレンス](https://docs.docker.com/)

プログラムやデータを「コンテナ」に隔離する仕組みを提供してくれるプラットフォーム

【なぜ使うのか？】
各々のPCで開発を進める上で、プログラムの実行環境を共有しないと不具合が起きがち
↓
Dockerを使えば実行環境をコンテナに隔離した形で複製・配布できるので、ホストPCの環境に依ることなく実行環境を共有することができる




## イメージとは

コンテナの「素」となる設計図のようなもの
- イメージを利用することによって、同一環境のコンテナを量産できる＆移動できる
- イメージは[DockerHub](https://hub.docker.com/)で取得できる


## コンテナ操作の基本

### コンテナの作成、削除と起動、停止

```
docker run イメージ名
# docker pull(イメージダウンロード)、docker create(コンテナ作成)、docker start(コンテナ起動)を
# まとめて実行するコマンド
```

```
docker stop コンテナ名
# コンテナを停止する
```


```
docker rm コンテナ名
# コンテナを削除する
```

```
docker ps (-a)
# 動いているコンテナ一覧を表示する(オプション-aで停止しているものも表示)
```




### イメージの削除

```
docker image ls
# イメージ一覧を表示する
# ここで削除したいイメージ名またはIDを確認する
```

```
docker image rm イメージ名
# イメージを削除する
# 削除対象のイメージから作成したコンテナが削除されていないと、イメージの削除は実行できない
```

## Dockerで複数のコンテナを動かす

基本を確認したところで、まずはDocker Composeを使わずに複数のコンテナを作成し、通信を行いながら使用するケースを考えてみます。
例えばWebサイト作成に使われるWordPressというソフトウェアを使用する場合、
- WordPressのコンテナ
- データベースのコンテナ

の2つを作成する必要があります。

ここで、Dockerは
- 一度に1つのコンテナしか動かせない
- コンテナ同士が通信するためのDockerネットワークの作成が必要

という理由から、以下の手順が必要になります。

1. コンテナ同士が通信するためのネットワークを作成する
    `docker network create ネットワーク名`
    
2. データベース（例：MySQL）コンテナの作成と起動
     `docker run --name MySQLのコンテナ名 -dit --net=ネットワーク名 -e MYSQL_ROOT_PASSWORD=MySQLのルートパスワード -e MYSQL_DATABASE=MySQLのデータベース領域名 -e MYSQL_USER=MySQLのユーザー名 -e MYSQL_PASSWORD=MySQLのパスワード mysql --character-set-server=文字コード --collation-server=照合順序`
     
3. WordPressコンテナの作成と起動
    `docker run --name WordPressのコンテナ名 -dit --net=ネットワーク名 -p ポートの設定(ホストマシンのポート番号:コンテナのポート番号) -e WORDPRESS_DB_HOST=データベースのコンテナ名 -e WORDPRESS_DB_NAME=データベース領域名 -e WORDPRESS_DB_USER=データベースのユーザー名 -e WORDPRESS_DB_PASSWORD=データベースのパスワード wordpress`

※後述のボリュームの指定は省略しています
-eオプションは環境変数の設定です。使用するネットワーク名やポート、環境変数など指定するものが多いので、コマンド文が長いですね。しかもコンテナの数だけ起動、停止、削除などを行う必要があり大変です。

## Docker Compose
### Docker Composeとは
ここで登場するのがDocker Composeです。
>Compose とは、複数のコンテナを定義し実行する Docker アプリケーションのためのツールです。
>[公式リファレンス/DockerCompose概要より](https://docs.docker.jp/compose/index.html#compose-features)

Docker ComposeはDocker Engineとは別のソフトウェアですが、デスクトップ版にはすでに入っているため、Docker Desktop for Windows/Macを使用している場合はインストールなくそのまま利用できます。

複数コンテナの構築に関わるコマンド文の内容を1つの定義ファイルに書き込むことで、構築や停止、破棄を一気に実行することができます。

### 定義ファイル
以下は定義ファイルの例です。
```YAML
services:
  db(サービス名):
    image: mysql
    networks:
      - ネットワーク名
    volumes:
      - MySQLのボリューム名:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: MySQLのルートパスワード
      MYSQL_DATABASE: MySQLのデータベース領域名
      MYSQL_USER: MySQLのユーザー名
      MYSQL_PASSWORD: MySQLのパスワード
  web(サービス名):
    depends_on:
      - MySQLのコンテナ名
    image: wordpress
    networks:
      - ネットワーク名
    volumes:
      - WordPressのボリューム名:/val/www/html
    ports:
      - ポートの設定(ホストマシンのポート番号:コンテナのポート番号)
    restart: always
    environment:
      WORDPRESS_DB_HOST: データベースのコンテナ名
      WORDPRESS_DB_NAME: データベースの領域名
      WORDPRESS_DB_USER: データベースのユーザー名
      WORDPRESS_DB_PASSWORD: データベースのパスワード
networks:
  ネットワーク名:
volumes:
  MySQLのボリューム名:
  WordPressのボリューム名:
```
大項目「services」「networks」「volumes」を抜き出してみるとこんな感じです。

```YAML
services:
  db(サービス名):
  web(サービス名):
networks:
  ネットワーク名:
volumes:
  MySQLのボリューム名:
  WordPressのボリューム名:
```
「services」には各コンテナの情報を、
「networks」「volumes」にはそれぞれネットワークとボリュームの情報を載せていきます。
「services」項目の各コンテナの情報の中身は、よくみるとdockerコマンドで打っていた内容とほぼ同じですね。

:::note info
**ボリュームとマウントについて**
コンテナを削除すると、コンテナ内のデータも削除されます。
データを永続化するには、コンテナ内のデータがあるディレクトリと、コンテナ外の任意のディレクトリを結びつけ（マウント）する必要があります。
コンテナ外の結びつけ先としてよく使われるのは以下の2種類です。
 - Docker Engineが管理している領域内(ボリュームマウント)
 - ホストPCのディレクトリなど(バインドマウント)

 上述の定義ファイルの大項目「volumes」でボリューム名を定義しておくと、「services」内の「volumes」項目の中でデータの結び付け先として利用することができます。
 
 【参考】 
 [Docker の Volume がよくわからないから調べた](https://qiita.com/aki_55p/items/63c47214cab7bcb027e0)
 [[Docker for Mac] Docker Volumeの実態がどこにあるのか、探してみた](https://note.com/w0o0ps/n/n9bc1bcd9fa59)
:::

### 定義ファイルの名前
>The default path for a Compose file is `compose.yaml` (preferred) or `compose.yml` that is placed in the working directory. Compose also supports `docker-compose.yaml` and `docker-compose.yml` for backwards compatibility of earlier versions. If both files exist, Compose prefers the canonical `compose.yaml`.
[docker.docs](https://docs.docker.com/compose/compose-application-model/)

上記の通り、現在公式の推奨は`compose.yaml`ですが、`compose.yml`、後方互換として`docker-compose.yaml`と`docker-compose.yml`もサポートされています。

    
### Dockerfileとの違い
Docker関連のファイルとして、Docker Compose用の定義ファイルの他にDockerfileがあります。
Docker Composeはいわばdocker runコマンドの集合体で、コンテナやネットワーク、ボリュームなどを作成できます。これに対しDockerfileはイメージを作るものであり、ネットワークやボリュームを作成することはできません。
ちなみにDocker Composeの定義ファイルの中で、Dockerfileのイメージをビルドしてコンテナを作成するよう記述することができます。
```YAML
…（省略）
  web(サービス名):
    depends_on:
      - MySQLのコンテナ名
    build: .
    networks:
      - ネットワーク名
…（省略）
```
上記のように、image:の代わりにbuild:とし、compose.yamlファイルからDockerfileへの相対パスを記述します。

### docker compose実行の流れ
1. （必要があれば）Dockerfileの作成
2. compose.yamlの作成
3. コンテナの起動
    ```
    docker compose up 
    # docker runのように、イメージのダウンロード、コンテナ作成、起動などを行うコマンド
    ```
4. コンテナの削除
    ```
    docker compose down
    # コンテナとネットワークが停止・削除される。
    # ボリュームとイメージはそのまま残っているので、必要であれば手動で削除する。
    ```
## 終わりに
今までなんとなく使っていたDocker Composeですが、調べてみることでありがたみを感じると同時に少しずつ解像度が上がってきました。知るほどにわからないことも出てくるので、今後もDockerを使いつつ知識をつけていきたいと思います。

## 参考文献
[公式リファレンス](https://docs.docker.com/)
[Docker＆Kubernetesのきほんのきほん](https://www.amazon.co.jp/%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-Docker-Kubernetes%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E5%B0%8F%E7%AC%A0%E5%8E%9F%E7%A8%AE%E9%AB%98/dp/4839972745/ref=tmm_pap_swatch_0?_encoding=UTF8&dib_tag=se&dib=eyJ2IjoiMSJ9.whJlBE-tVkKEt_7HTbfq_8h6ucY6V9wXqCUYSz7Ya7DddOD9jlVRwMBSScuUGyGZtbD-r5wj7qS2lfZWqbeOi0gzQibbEothxRkIzZmgfkTUDKHYQTobM_dq9EQs3l15JdfemkKKxkrvn27nPT-Qt2ySCzqOB6H7FQ0v7tRc9-Q38B4PJiWiTt9U8emnBsJ1mlZTMpvafyglG5v5Lyx3bAN0RTTV3wVVUdth9cBIKH_YTfAUrYNWBAt01A8l8KqgkBoCjnq_ud3FPsslmsPdCWBeNfQCgUaspspACjh-OIs.iCqrp30lzb51CAS_jMJU96upVqPo5JqDueQHvyacCxU&qid=1722608120&sr=8-1)
 [Docker の Volume がよくわからないから調べた](https://qiita.com/aki_55p/items/63c47214cab7bcb027e0)
 [[Docker for Mac] Docker Volumeの実態がどこにあるのか、探してみた](https://note.com/w0o0ps/n/n9bc1bcd9fa59)
[個人的docker composeおすすめtips 9選](https://future-architect.github.io/articles/20240620a/)