KAKUTA TECH BLOG

Blog Article

DockerfileやDocker Composeについて

はじめに

Docker を使ってアプリケーションを動かすとき、Dockerfile と Docker Compose はよく登場します。どちらも設定をファイルに記述しますが、役割は異なります。本記事では、Dockerfile、Docker Compose、Docker イメージのレイヤについて、基本的な仕組みと使い分けを説明します。

参考リンク

Dockerfileとは

Dockerfile は、Docker イメージを構築するための手順を記述したテキストファイルです。

Docker イメージとは、コンテナを起動するときに使用する、アプリケーションの実行環境をまとめたものです。Dockerfile には、どのイメージを土台にするのか、必要なファイルをどこへ配置するのか、必要なパッケージをどうインストールするのか、コンテナ起動時に何を実行するのか、といった情報を記述します。

Docker は Dockerfile に書かれた命令を上から順番に処理し、その内容をもとに Docker イメージを構築します。

🔰一言で言うと「Docker イメージをどう作るかを定義するファイル」です。

FROM でベースイメージを指定する

FROM は、Docker イメージを構築するときの土台となるイメージを指定します。

FROM ubuntu:24.04

ubuntu:24.04 を土台として、その上に必要なファイルやパッケージなどを追加していきます。

Docker では、Ubuntu のような OS 環境だけでなく、Node.js や Python などの実行環境が用意されたイメージをベースとして利用することもできます。

WORKDIR で作業ディレクトリを指定する

WORKDIR は、Dockerfile の後続の命令や、コンテナ起動後の作業ディレクトリを指定します。

WORKDIR /app

この場合、以降の RUN、COPY、CMD などで /app を基準として扱いやすくなります。

COPY でファイルをコピーする

COPY は、Docker のビルドコンテキストにあるファイルやディレクトリを、イメージ内へコピーするために使用します。

COPY . .

この場合、現在のビルドコンテキストにあるファイルを、WORKDIR で指定した /app にコピーします。

RUN でビルド時の処理を実行する

RUN は、Docker イメージを構築するときにコマンドを実行します。

RUN apt-get update && apt-get install -y python3

この例では、パッケージ情報を更新したあと、Python 3 をインストールしています。

RUN は、アプリケーションを実行するための環境をイメージの中に用意するときに使用します。

EXPOSE で使用するポートを示す

EXPOSE は、コンテナが使用するポートをイメージのメタデータとして示します。

EXPOSE 80

ただし、EXPOSE を記述しただけでホスト側からアクセスできるようになるわけではありません。

ホスト側のポートとコンテナのポートを接続して外部からアクセスできるようにする場合は、docker run -p や Docker Compose の ports などを使用します。

CMD でコンテナ起動時のコマンドを指定する

CMD は、コンテナを起動したときに実行するデフォルトのコマンドを指定します。

CMD ["python3", "app.py"]

この場合、コンテナを起動すると python3 app.py が実行されます。

RUN がイメージを構築するときに実行されるのに対して、CMD は基本的にコンテナを起動したときに実行される、という違いがあります。

Docker Composeとは

Docker Compose は、複数のコンテナから構成されるアプリケーションを定義し、まとめて管理するための仕組みです。

たとえば、Web アプリケーションとデータベースを別々のコンテナで動かす場合、それぞれのコンテナを個別にコマンドで起動することもできます。しかし、コンテナが増えるほど、起動方法やネットワーク、ボリュームなどを個別に管理するのは大変になります。

Docker Compose を使うと、これらの構成を Compose ファイルにまとめて記述できます。

現在の Docker Compose では、compose.yaml などの Compose ファイルに、アプリケーションを構成するサービス、ネットワーク、ボリュームなどを定義します。

compose.yaml の基本構成

例えば、Web アプリケーションとデータベースを構成する場合は、次のようにサービスを定義できます。

services:
  web:
    build: .
    ports:
      - "3000:3000"

  db:
    image: postgres:18

web と db が、それぞれアプリケーションを構成するサービスです。

web では build によって Dockerfile を使ったイメージのビルド方法を指定し、ports でホストとコンテナのポートを接続しています。

一方、db では既存の PostgreSQL イメージを使用しています。

このように Docker Compose では、各サービスをどのようなコンテナとして動かすのかをまとめて定義できます。

Docker ComposeとDockerfileの違い

Dockerfile と Docker Compose は、どちらも Docker の構成をファイルに記述するため混同しやすいですが、担当する範囲が異なります。

Dockerfile

Dockerfile は、1つの Docker イメージをどのように構築するかを定義します。

FROM node:24

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["npm", "start"]

この Dockerfile では、Node.js のイメージを土台として、アプリケーションのファイルをコピーし、依存パッケージをインストールし、コンテナ起動時にアプリケーションを実行するよう設定しています。

つまり、Dockerfile の中心的な役割はイメージの作成方法を定義することです。

Docker Compose

Docker Compose は、アプリケーションを構成するサービスをどのように組み合わせて動かすかを定義します。

services:
  web:
    build: .
    ports:
      - "3000:3000"

  db:
    image: postgres:18

この Compose ファイルでは、web と db という 2 つのサービスを定義しています。

web は Dockerfile を利用してイメージをビルドし、db は PostgreSQL の既存イメージを利用しています。

このように、Dockerfile はイメージを作るための設計図、Docker Compose は複数のサービスを組み合わせて動かすための構成ファイルと考えると分かりやすくなります。

Docker Compose から Dockerfile を利用することもできるため、両者は別々に使うものではなく、組み合わせて使うことも多くあります。

Dockerにおけるレイヤとは

Docker イメージは、1つの巨大なファイルとして単純に保存されているわけではありません。Docker イメージは、複数のレイヤを積み重ねて構成される仕組みになっています。

Dockerfile に記述した RUN、COPY、ADD などの命令によって、イメージに変更が加えられ、その変更がレイヤとして扱われます。

また、FROM で指定するベースイメージ自体も、複数のレイヤから構成されている場合があります。

このレイヤ構造によって、既に存在する部分を再利用しながらイメージを構築できるため、ビルドを効率化できます。

レイヤとキャッシュ

Docker はイメージのビルド時にキャッシュを利用します。

Dockerfile の命令や、その命令に必要な内容に変更がなければ、以前のビルド結果を再利用できる場合があります。

例えば、次のような Dockerfile があるとします。

FROM node:24

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["npm", "start"]

依存関係を定義する package.json などに変更がなければ、npm install の結果をキャッシュから再利用できる可能性があります。

そのため、Dockerfile では、変更されにくい処理を前に、変更されやすい処理を後ろに配置することで、キャッシュを利用しやすくする設計がよく行われます。

Docker Composeの基本操作

Docker Compose では、docker compose コマンドを使ってサービスを操作します。

イメージをビルドする

docker compose build

Compose ファイルで build が設定されたサービスのイメージをビルドします。

Dockerfile やビルド対象のファイルを変更して、その変更をイメージに反映したい場合にも使用します。

コンテナを作成・起動する

docker compose up -d

Compose ファイルに定義されたサービスのコンテナを作成・起動します。

-d はバックグラウンドで起動するためのオプションです。イメージのビルドも同時に行いたい場合は、次のようにします。

docker compose up -d --build

コンテナを停止・削除する

docker compose down

Compose によって作成されたコンテナやネットワークなどを停止・削除します。

コンテナの状態を確認する

docker compose ps

Compose で管理しているコンテナの状態を確認できます。

ログを確認する

docker compose logs

Compose の各サービスで動作しているコンテナのログを確認できます。

サービスで一度だけコマンドを実行する

docker compose run <サービス名> <コマンド>

特定のサービスについて、一度だけコマンドを実行したい場合に使用します。

起動中のコンテナでコマンドを実行する

docker compose exec <サービス名> <コマンド>

すでに起動しているサービスのコンテナ内でコマンドを実行します。

例えば、コンテナ内のシェルを操作したい場合は次のようにします。

docker compose exec web sh

Dockerfileを変更したときの反映方法

Dockerfile を変更した場合、その変更を既に作成されているイメージへ自動的に反映するわけではありません。

そのため、変更した Dockerfile を使ってイメージを再ビルドし、そのイメージを使ってサービスを起動します。

docker compose build
docker compose up -d

また、ビルドと起動をまとめて行う場合は、次のコマンドでも実行できます。

docker compose up -d --build

Docker Compose では、このように Dockerfile でイメージを作り、Compose でそのイメージを含むサービス全体を起動・管理するという関係になります。

まとめ

Dockerfile と Docker Compose の違いは、担当する範囲を見ると理解しやすくなります。

項目

Dockerfile

Docker Compose

主な役割

Docker イメージを構築する

サービスを構成・起動する

記述する内容

イメージの構築手順

サービス、ネットワーク、ボリュームなど

主な対象

イメージ

アプリケーション全体の構成

関係

イメージを作る

Dockerfile から作ったイメージなどを利用してサービスを動かす

🔰一言で言うと、Dockerfile は「イメージをどう作るか」を定義し、Docker Compose は「複数のサービスをどう組み合わせて動かすか」を定義するものです。

また、Docker イメージはレイヤを積み重ねて構成されており、ビルドキャッシュを利用することで、変更されていない部分を再利用しながら効率的にイメージを構築できます。