🐙

DockerのDockerfileとdocker-compose.ymlについて調べてみた(自分用メモ)

に公開2

プロジェクトでよく使うDockerの仕組みについて

今回は、プロジェクトでよく利用されるDockerについて、その仕組みを調べました。

この記事は、Dockerの全体像を大まかに把握することを目的としており、「木を見て森を見ず」ということわざでいう「森」の部分に焦点を当てています。

Dockerを使い始めると、Dockerfiledocker-compose.ymlといったファイルを目にすることが多くなります。本記事では、これらのファイルの役割について整理していきます。

※本記事の内容は、一般的な情報を基に調べています。もし誤った点などございましたら、ご指摘いただけますと幸いです。


そもそもDockerとは何でしょうか? 🤔

Dockerとは、「コンテナ」と呼ばれる、OSレベルで隔離された実行環境を構築するための技術です。

アプリケーション本体と、その動作に必要なライブラリや設定などを一つにまとめることができます。このまとめたパッケージを「コンテナ」として動かすことで、ご自身のPCでも、他の開発者のPC、あるいは本番サーバー上でも、どこでも同じようにアプリケーションを動作させることが可能になります。

この「コンテナ」を作成するための手順書や設定ファイルが、Dockerfiledocker-compose.ymlにあたります。

Dockerfile の役割 📜 - コンテナの作り方を記述する手順書

Dockerfileは、一つのコンテナをどのように作成するかを定義するためのファイルです。テキストファイル形式で、中には実行されるべきコマンドが順番に記述されています。これらのコマンドが上から順に実行されることで、コンテナの元となる「イメージ」が作成されます。

例として、Pythonアプリケーションを動作させるための、一般的なDockerfileを見てみましょう。

backend/dockerfile
# ベースにするイメージを指定
FROM python:3.11

# 環境変数を設定
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# コンテナ内での作業ディレクトリを指定
WORKDIR /usr/src/app

# 依存ライブラリのリストをコピー
COPY ./requirements.txt /usr/src/app/requirements.txt

# リストを元にライブラリをインストール
RUN pip install -r requirements.txt

# アプリのソースコードをコピー
COPY . /usr/src/app

# コンテナ起動時に実行するコマンド
CMD ["python", "main.py"]

各行が何を実行しているのか、以下で解説します。

  1. FROM python:3.11

    • python:3.11という、公式から配布されているPython環境がインストール済みのイメージを、コンテナの土台として使用することを意味します。
  2. ENV ...

    • Pythonの挙動を調整するための環境変数を設定します。例えば、キャッシュファイルを作成しない、バッファリングを無効にするといった設定が含まれます。
  3. WORKDIR /usr/src/app

    • コンテナ内部で、以降のコマンドを実行する際の作業場所(ディレクトリ)を指定します。
  4. COPY ./requirements.txt ...

    • ご自身のPC(ホストPC)にあるrequirements.txtファイルを、コンテナ内の/usr/src/app/へコピーするための命令です。requirements.txtは、プロジェクトに必要なライブラリの一覧が記述されたファイルです。
  5. RUN pip install -r requirements.txt

    • コンテナ内でpip installコマンドを実行し、先にコピーしたrequirements.txtに基づいてライブラリをインストールします。
  6. COPY . /usr/src/app

    • ホストPCのカレントディレクトリにあるソースコードなどのファイル一式を、コンテナにコピーします。
  7. CMD ["python", "main.py"]

    • このコンテナが起動した際に、デフォルトで実行されるコマンドです。この例ではpython main.pyを実行し、アプリケーションを起動します。

このように、Dockerfileは、クリーンなコンテナ環境に、どのようなアプリケーションを入れ、どのような設定を行い、最終的にどうやって起動させるか、という一連の手順を記述したものになります。


docker-compose.yml の役割 🎼 - 複数のコンテナをまとめて管理する設定ファイル

一方、docker-compose.ymlは、複数のコンテナをまとめて定義し、それらを連携させたり、一括で起動・停止したりするためのファイルです。YAMLという形式で記述します。

実際のWebアプリケーションでは、フロントエンド、バックエンド、データベースのように、複数のサービス(コンテナ)が連携して動作することが多いです。そのような場合に、このdocker-compose.ymlを使用すると非常に便利です。

docker-compose.yml
# services: ここに、動かしたいコンテナの定義を記述します
services:
  # フロントエンド用のコンテナ定義
  webapp:
    build: ./frontend # Dockerfileがある場所
    ports:
      - "3000:3000"  # ポートの紐付け
    volumes:
      - ./frontend:/usr/src/app # フォルダの共有

  # バックエンド用のコンテナ定義
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    volumes:
      - ./backend:/usr/src/app

  # データベース用のコンテナ定義 (今回は例として記述)
  # db:
  #   image: mysql:8.0 # Dockerfileからではなく、直接イメージを指定することも可能です
  #   volumes:
  #     - db-data:/var/lib/mysql
  #   environment:
  #     - MYSQL_ROOT_PASSWORD=supersecret
  #     - MYSQL_DATABASE=mydatabase
#
# volumes: # データを永続化させるためのボリューム定義
#   db-data:

こちらの各項目の意味も見ていきましょう。

  • services:: ここに、webappbackendといった、起動したいコンテナごとの設定を記述していきます。

  • build: ./frontend: frontendというディレクトリにあるDockerfileを使用して、コンテナをビルド(構築)することを指定します。

  • ports: - "3000:3000": これはポートフォワーディングと呼ばれる仕組みです。左側がホストPCのポート番号、右側がコンテナのポート番号を表します。この設定により、localhost:3000へアクセスすると、webappコンテナの3000番ポートへ接続されるようになります。

  • volumes: - ./frontend:/usr/src/app: これはボリュームマウントと呼ばれる機能です。ホストPCの./frontendフォルダと、コンテナ内の/usr/src/appフォルダを共有(同期)します。この設定を行うことで、ホストPCでコードを修正した際に、コンテナを再起動することなく変更がリアルタイムに反映されるため、開発効率が大幅に向上します。

docker-compose.ymlを記述しておけば、docker-compose upというコマンド一つで、定義された全てのコンテナが起動します。反対にdocker-compose downで全てのコンテナを停止でき、管理が非常に容易になります。

まとめ 📝

今回の内容をまとめます。

  • Dockerfile
    • 1つのコンテナの「作り方」を定義する手順書です。
  • docker-compose.yml
    • 複数のコンテナの「構成」を定義する設定ファイルです。各コンテナをどのように連携させ、管理するかを記述します。

単体のシンプルなアプリケーションであればDockerfileだけでも対応可能ですが、複数のサービスが連携するようなシステムではdocker-compose.ymlを使用するのが一般的っぽいです。

Discussion

rakiraki

調べるなら一次情報にあたるべきです。
https://docs.docker.com/compose/intro/compose-application-model/

docker-compose は既に終わっていて docker compose が正しいです。
yamlファイルも docker-compose.yaml ではなく compose.yaml が現在の標準です。

yusukenyusuken

情報提供、ありがとうございます!
なるほど、私の携わっていたプロジェクトは古いのですね。
ご指摘いただいて勉強になりました!ありがとうございます☺️