Dockerfile / docker-compose.yml / compose.yaml の違い

# はじめに

Dockerを使用した開発に出てくるファイルは、基本的に以下の３つです。

- `Dockerfile`
- `docker-compose.yml`
- `compose.yaml`

どのような違い・関係があるのでしょうか。
# それぞれの用途

| ファイル名                | 用途                                             |
| -------------------- | ---------------------------------------------- |
| `Dockerfile`         | イメージのビルドで使用される。<br>コンテナ実行のための依存関係・設定が書かれたファイル。 |
| `docker-compose.yml` | 複数のコンテナを管理する。<br>`Dockerfile`の場所を指定することができる。   |
| `compose.yaml`       | `docker-compose.yml`と同じ。名称の好みの違い。              |

## `Dockerfile` の例

Railsの例

```
# Rubyのベースイメージを指定
FROM ruby:3.1.4

# 必要なパッケージのインストール
RUN apt-get update -qq && apt-get install -y nodejs npm && npm install --global yarn

# アプリケーションディレクトリを作成
RUN mkdir /myapp
WORKDIR /myapp

# GemfileとGemfile.lockをコピー
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock

# Bundlerを介してGemをインストール
RUN bundle install

# Yarnを介してJavaScriptの依存関係をインストール
COPY package.json yarn.lock ./
RUN yarn install --check-files

# アプリケーションのソースコードをコピー
COPY . /myapp

# アプリケーションがリッスンするポートを指定
EXPOSE 3000

# データベースの設定（必要に応じて）
# RUN rails db:create
# RUN rails db:migrate

# アプリケーションの起動コマンド
CMD ["rails", "server", "-b", "0.0.0.0"]

```


## `docker-compose.yml` の例

ディレクトリ構成
```
root/
  ├ Dockerfile
  └ docker-compose.yml
```

`docker-compose.yml`

```yml:docker-compose.yml
version: '3.8'
services:
  # "db"サービスでは"image: "を指定し、そのイメージからコンテナをビルドする。
  db:
    image: postgres:13
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"

# "web"サービスには"image: "の設定がなく、代わりにDockerfileを参照する"build: "設定がある。
  web:
    build: . # 同じ階層のDockerfileを参照するよう指示。
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://postgres:password@db:5432/myapp_development
    depends_on:
      - db

volumes:
  postgres_data:
```

上記の例では `build: .` としましたが、「Dockerfileに特定の名前がついている場合」他の記法を使用します。
（Dockerfileに名前を付ける場合、`Dockerfile.web`といった、拡張子のような形で名づけができます。）

ディレクトリ構成
```
root/
  ├ Dockerfile.db
  ├ Dockerfile.web
  └ docker-compose.yml
```


```yml:docker-compose.yml
services:
  # 以下のように名前を指定する。
  db:
    build: .db 
  # 省略
  # "context"属性, "dockerfile"属性を使用して、フルネームの指定も可能
  web:
    build:
      context: .
      dockerfile: Dockerfile.web
    # 省略
```
## `docker-compose.yml`と`compose.yaml`の違い

機能は同じです。

<font color="Orange">公式には、`compose.yaml`が推奨されています。</font>

https://docs.docker.com/compose/compose-application-model/

> 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.

ただ、慣習的に`docker-compose.yml`もまだまだ使われている印象があります。
なんなら、大多数がそうかも。

`docker`全体として、後方互換性を持ち続け、実際に改定前のものも多用される傾向があるので（`docker ps` / `docker images`など）
<font color="Orange">`docker-compose.yml`を使うか、`compose.yaml`を使うかは好みである</font>と言ってよいと思います。
好みがなければ`compose.yaml`を使うと良いかもしれません。

# おわりに

改めて振り返ります。

| ファイル名                | 用途                                             |
| -------------------- | ---------------------------------------------- |
| `Dockerfile`         | イメージのビルドで使用される。<br>コンテナ実行のための依存関係・設定が書かれたファイル。 |
| `docker-compose.yml` | 複数のコンテナを管理する。<br>`Dockerfile`の場所を指定することができる。   |
| `compose.yaml`       | `docker-compose.yml`と同じ。名称の好みの違い。              |

- `docker-compose.yml`から`Dockerfile`を参照する
- `docker-compose.yml`と`compose.yaml`は同じもの

大まかに、こんな関係だと覚えておけば大丈夫そうです。