Dockerfileとdocker-compose.ymlの違いと基本的な書き方

# はじめに
ITスクールで学習中のnaruです。
アプリ開発を進める中で、Dockerfileについて調べていた際に、「docker-compose.ymlって何だっけ？Dockerfileとどう違うの？」と疑問に思いました。そこで、学んだことをアウトプットするために、初めて記事を書いてみました。
# １.　Dockerfileとは？
**Dockerfileとは、Dockerイメージを作成するために必要な設定ファイル**のことです。
この設定ファイルをビルドすることによって、Dockerイメージが作成されます。

ただしdocker hubにあるイメージをそのまま使う場合はdocker-compose.ymlに直接imageを指定すれば良いため、Dockerfileはなくても問題ありません。
（Dockerファイルを書けるようになると、自分で好きなようにカスタマイズしたDockerイメージを作成できる）

 Dockerイメージ？ビルド？となった方は、Dockerの各要素とコンテナ起動までの仕組みが初心者にわかりやすく図解付きで解説しているので、載せておきます。
 
 https://o2mamiblog.com/docker-beginner-1/
 
# ２.　docker-compose.ymlとは？
**YAML形式を用いて書いた、Docker Composeの設定ファイル**のことです。
Docker Composeとは、複数のDockerコンテナを1度にまとめて操作出来るツールです。（Dockerが標準で搭載しているDocker Engineでは、1度に1つずつしかDockerコンテナを操作できない。）

**docker-compose.yml**はDocker Composeコマンドを使用することによって、複数のコンテナを一括して操作でき、イメージのビルドやコンテナの作成が簡単に行えます。これにより、複雑なマルチコンテナ環境を簡単に構築および管理できます。

# ３.　Dockerfileの書き方
Flaskアプリケーションをコンテナ化する場合のディレクトリ構造の例を使って説明していきます。
### ディレクトリ構成例
```:bash

/my_flask_project
  ├── app/
  │   ├── app.py               # Flask アプリのメインファイル
  │   ├── __init__.py          # Flask パッケージの初期化ファイル
  │   └── templates/           # HTML テンプレートを格納するディレクトリ
  │       └── index.html       # サンプル HTML ファイル
  ├── requirements.txt         # Python の依存関係をリスト化したファイル
  ├── Dockerfile               # Docker イメージをビルドするための設定ファイル
  └── docker-compose.yml       # サービス全体を定義する Compose ファイル

```
### Dockerfileの例
```docker:dockerfile

#（１）
FROM python:3.11-slim  

#（２）
WORKDIR /app

#（３）
COPY requirements.txt requirements.txt

#（４）
RUN pip install --no-cache-dir -r requirements.txt

#（３）
COPY app/ /app/

#（５）
CMD ["python", "app.py"]

```
## （１）FROM
```DOCKER:
FROM python:3.11-slim 
```
ベースイメージを指定します。
ここでは、軽量な Python 3.11 の公式イメージ python:3.11-slim を使用しています。
## （２）WORKDIR
```docker:
WORKDIR /app
```
コンテナ内の作業ディレクトリを指定します。
これ以降のすべてのコマンドはこのディレクトリ内で実行されます。
## （３）COPY
```docker:
COPY requirements.txt requirements.txt
```
**COPY <ホストのパス> <コンテナ内のパス>**

ホストマシンのファイルをコンテナ内にコピーします。
requirements.txt をコンテナにコピーして依存関係をインストールします。
```docker:
COPY app/ /app/
```
アプリケーションコード（app/ ディレクトリ全体）を /app にコピーします。
## （４）RUN
```docker:
RUN pip install --no-cache-dir -r requirements.txt
```
コンテナのビルド時に実行されるコマンドを指定します。
pip install コマンドで requirements.txt に記載された依存関係（Flask）をインストールします。
--no-cache-dir オプションでキャッシュを無効化し、イメージサイズを小さくします。
## （５）CMD
```docker:
CMD ["python", "app.py"]
```
コンテナ実行時に実行されるデフォルトコマンドを指定します。
ここでは python app.py を実行して Flask アプリケーションを起動します。
# ４.　docker-compose.ymlの書き方
```yaml:docker-compose.yml

version: '3.9' #（１）

services: #（２）
  web:
    build: #（３）
      context: .
      dockerfile: Dockerfile
    ports: #（４）
      - "5000:5000"
    volumes: #（５）
      - ./app:/app
    environment: #（６）
      - FLASK_ENV=development
      
```
## （１）version
```yaml
version: '3.9'
```
Docker Compose ファイルのバージョンを指定します。
## （２）services
```yaml
services: 
  web:
```
コンテナ化されたサービスを定義します。
web はサービスの名前（Flask アプリを動かすコンテナ）。
## （３）build
```yaml
build: 
      context: .
      dockerfile: Dockerfile
```
イメージをビルドする設定。
**context**: 現在のディレクトリ（.）をビルドコンテキストとして指定。
Docker はこのディレクトリ内のすべてのファイルとサブディレクトリにアクセスします。
**dockerfile**:ビルドに使用する Dockerfile を指定。
## （４）ports
```yaml
ports: 
      - "5000:5000"
```
ホストマシンとコンテナ間のポートをマッピングします。

**ホストマシンのポート番号:コンテナのポート番号**
5000:5000 は、ホストの 5000 番ポートをコンテナの 5000 番ポートに接続。
## （５）volumes
```yaml
volumes: 
      - ./app:/app
```
ホストマシンの app/ ディレクトリ をコンテナ内の /app にマウントします。

**volumes**:ホストマシンと Dockerコンテナの間でファイルやディレクトリを共有します。これにより、コンテナ内のデータとホストマシンのデータを同期させたり、永続化したりできます。
## （６）environment
```yaml
environment: 
      - FLASK_ENV=development
```
Dockerのコンテナ内で使用される環境変数を設定するために使用します。
Dockerコンテナはホストマシンの環境と完全に分離されて動作するため、コンテナ内部で環境変数を設定する必要があります。

FLASK_ENV=development に設定することで、Flask を開発モードで起動（デバッグ機能が有効）。

# おわりに
この記事では、Dockerfileとdocker-compose.ymlについて解説しました。プロジェクトの要件によって記述内容は変わるため、実際に使いながら理解を深めていきたいと思います。

初学者の記事ですので、間違っている点がありましたらご指摘頂けると助かります。