DockerfileはDockerインスタンスを構築するためのテキストファイルです。
このファイルにコマンドを記載することで、Dockerインスタンスの構築からデプロイまでを自動化できます。
この記事ではDockerfileの基本構造や使い方、コマンドの解説、実用例までを解説します。
Dockerfileの基本と詳細
Dockerfileの基本構造
Dockerfileはテキスト形式のファイルです。
以下に、基本的なDockerfileの例を示します。
FROM python:3.9-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Dockerfileは、コマンドを順に実行します。
主な指示は下記の通りです。
FROM
Dockerfile の最初に記述される命令で、基盤(ベース)となるDockerイメージを指定します。
ここで指定されたイメージを基にして、新しいDockerイメージが作成されます。
FROM python:3.9-slim
Pythonイメージ:
Python公式が提供するDockerイメージで、Python 3.9がインストールされます。
slim バージョン:
Pythonイメージの軽量版で、通常のPythonイメージに比べて不要なライブラリやツールが削除され、サイズが小さくなっています。
以降の命令(例: RUN, COPY, CMD など)は、このpython:3.9-slimの環境上で実行されます。
WORKDIR
コンテナ内の作業ディレクトリを設定します。
このディレクトリが以降のすべての相対パスの基準になります。
WORKDIR /app
コンテナ内で以降の命令(例: RUN, CMD, ENTRYPOINT, COPY, ADD など)が実行されるデフォルトのディレクトリを指定します。
上記の例では、作業ディレクトリとして /app を設定しています。
指定されたディレクトリ(ここでは /app)が存在しない場合、Dockerはそのディレクトリを自動的に作成します。
RUN
Dockerfile内でコマンドを実行するための命令です。
コマンドを実行し、インスタンスに添加する処理を記載します。
RUN apt-get update && apt-get install -y curl
この場合、apt-get を使用してパッケージを更新・インストールするコマンドを実行します。
実行された結果は、新しいレイヤーとしてDockerイメージに追加されます。
COPY/ADD
ファイルをコピーします。
COPYはローカルファイルをコピー、ADDはリモートリソースもコピーできます。
COPY app /app
COPY は、ローカル(ビルドコンテキスト)のファイルやディレクトリをコンテナ内にコピーするためのDockerfile命令です。
ビルドコンテキストとは、docker build コマンドで指定するディレクトリ(通常はDockerfileがあるディレクトリ)のことです。
構文: COPY <ソース> <ターゲット><ソース>: ホストマシン上のコピー元パス。<ターゲット>: コンテナ内のコピー先パス。
app
ソースパス: ビルドコンテキスト内のローカルディレクトリ app を指定しています。
ここでの app は、Dockerfileと同じディレクトリにあるサブディレクトリです。
/app
ターゲットパス: コンテナ内の /app ディレクトリに app の内容をコピーします。
ターゲットディレクトリ /app が存在しない場合は、自動的に作成されます。
権限の設定
コピーされたファイルの所有者と権限は、Dockerイメージ内でのデフォルトのユーザーとグループに従います(通常は root)。
CMD
インスタンスのデフォルトコマンドを指定します。
CMD ["/bin/bash"]
Dockerfileで定義されたコマンドをコンテナ実行時のデフォルト動作として指定します。CMD で設定されたコマンドは、コンテナが起動されたときに実行されます。
ENTRYPOINT
コンテナを定義し、コマンドの設定を小要素化しています。ENTRYPOINT でコマンドを固定化し、ユーザーに対して引数だけを設定できるインターフェースを提供することで、汎用的なイメージとして再利用性を高めます。
ENTRYPOINT ["python"]
ENTRYPOINT は、Dockerコンテナの実行開始時に必ず実行されるコマンドを指定する命令です。ENTRYPOINT は、ユーザーが docker run で引数を指定した場合でも、その引数を受け取って実行できます。
この点で、CMD と異なり、エントリーポイントを変更しない限り実行が保証されます。
詳細は、【初心者向け】DockerのENTRYPOINTとは?基本的な使い方とコンテナへの入り方を参照してください。
ホストPCとコンテナのディレクトリ構成
以下に、ホストPCとコンテナ内のディレクトリ構成の例を示します。
ホストPC
/my-project
├── app.py
├── requirements.txt
├── Dockerfile
└── other-files
Dockerfileの内容
FROM python:3.9-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
COPY . /appにより、ホストPCの/my-projectディレクトリ内のすべてのファイルが、コンテナ内の/appディレクトリにコピーされます。WORKDIR /appにより、すべてのコマンドはデフォルトで/appディレクトリで実行されます。- したがって、
pip install -r requirements.txtは/app内で実行されます。
コンテナ内
/app
├── app.py
├── requirements.txt
└── other-files
Dockerfileを使用したイメージ構築
Dockerfileを作成したら、Dockerイメージを構築するために「docker build」コマンドを実行します。下記に基本的な流れを示します。
Dockerfileを作成
以下のDockerfileを作成します:
Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Dockerイメージの構築
ターミナルで「docker build」を実行します。
docker build -t my-python-app .
Dockerコンテナの起動
作成したイメージを使用してコンテナを起動します:
docker run -d -p 5000:5000 my-python-app
実用例: WebアプリのDocker化
以下に、Node.jsを使用した簡易なWebアプリをDocker化する例を示します。
Dockerfile
FROM node:16
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
- WORKDIR /usr/src/app:
このコマンドはコンテナ内の作業ディレクトリを/usr/src/appに設定します。
このディレクトリが以降のすべての相対パスの基準になります。 - COPY package.json ./:
このコマンドは、ホスト側のpackage*.jsonファイルをコンテナ内の/usr/src/appディレクトリにコピーします。WORKDIRで指定したディレクトリが基準となるため、./は/usr/src/appを意味します。 - RUN npm install:
npm installは、作業ディレクトリである/usr/src/appで実行され、package.jsonに基づいて必要なパッケージがインストールされます。 - COPY . .:
ホスト側のカレントディレクトリのすべてのファイルをコンテナ内の/usr/src/appにコピーします。 - EXPOSE 3000:
コンテナがリッスンするポート3000を公開します。 - CMD [“npm”, “start”]:
コンテナが起動されたときに実行されるコマンドを指定します。この場合、Node.jsアプリケーションが開始されます。
docker-compose.yml
Docker Composeを使うと、複数のサービスを簡単にコンテナ化できます。
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/usr/src/app
command: npm start
- version: ‘3.8’:
Docker Composeファイルのバージョンを指定します。
この例では3.8を使用しています。 - services:
サービスの定義を開始します。
この例では、webという名前のサービスを定義しています。 - web:
サービスの名前です。
この名前は任意ですが、プロジェクト内で一意である必要があります。 - build: .:
Dockerfileが存在するディレクトリを指定します。
この場合、カレントディレクトリです。 - ports:
ホストとコンテナ間で公開されるポートを指定します。
この例では、ホストの3000番ポートをコンテナの3000番ポートにマッピングします。 - volumes:
ホストのディレクトリをコンテナ内にマウントします。
この例では、ホスト側のカレントディレクトリをコンテナの/usr/src/appにマウントしています。 - command: npm start:
コンテナが起動したときに実行されるコマンドを指定します。
この場合、Node.jsアプリケーションが開始されます。
CMDとcommandの必要性と優先順位
DockerfileのCMDとdocker-compose.ymlのcommandは、どちらもコンテナ起動時に実行されるコマンドを指定しますが、以下の違いがあります:
- 必要性:
コンテナを起動する際に実行すべきデフォルトのコマンドを定義する必要があるため、どちらか一方を指定します。CMDはDockerfileでイメージをビルドする際にデフォルトコマンドを設定し、commandはComposeファイルでサービス単位の上書きを提供します。 - 優先順位:
もし両方が指定されている場合、docker-compose.ymlのcommandが優先されます。
これにより、特定のサービスで異なるコマンドを実行したい場合に柔軟性を持たせることができます。 - 動作の違い:
例えば、DockerfileでCMD ["npm", "start"]と指定し、Composeファイルでcommand: npm run devを指定した場合、docker-compose upを実行するとnpm run devが実行されます。 - どちらか一方だけの場合:
- Dockerfileにのみ
CMDが指定されている場合、そのコマンドが実行されます。 docker-compose.ymlでのみcommandが指定されている場合、それが優先され、DockerfileのCMDは無視されます。
- Dockerfileにのみ
これにより、開発環境や本番環境に応じてコマンドを柔軟に切り替えることが可能です。
Dockerfile使用時のベストプラクティス
- キャッシュを最小化:
不要なファイルやレイヤーを含まないよう気をつけます。 - レイヤーリングを最適化:
チェインコマンドをマルチレイインで連続させ、イメージ構築時間を短縮します。 - Dockerファイルを.gitignoreに追加:
不要なファイルをコンテナに含めないようにします。
Dockerfileを正しく理解して使うことで、インフラ構築を高速化し、アプリのデプロイメントやテストの効率化を実現できます。

