はじめに
Dockerfileは、Dockerエコシステム内のカスタムイメージの基盤を形成します。この記事では、Dockerfileの構造について詳しく説明し、カスタムイメージを作成するために使用される一般的な命令を探索します。
Dockerfileの構造
典型的なDockerfileは、次の構成要素から構成されています。
-
ベースイメージ
これはカスタムイメージをビルドするための開始点です。Docker Hubで利用可能な公式またはコミュニティが作成したイメージの中から選択できます。 -
命令
これらは、ベースイメージを変更して新しいカスタムイメージを作成するコマンドです。 -
コメント
#
記号で始まる行はコメントとして扱われます。
一般的なDockerfileの命令
以下は、Dockerfileでもっとも頻繁に使用されるいくつかの命令の詳細です。
FROM
使用するベースイメージを指定します。この命令は必須であり、Dockerfileの最初の命令である必要があります。
FROM ubuntu:18.04
RUN
コマンドを実行し、その結果をコミットします。複数のRUN
命令は、イメージ内に別々のレイヤーを作成します。レイヤーを最小限に抑えるためには、&&
を使用してコマンドを組み合わせます。
RUN apt-get update && \
apt-get install -y nginx
CMD
コンテナが起動するときに実行するデフォルトのコマンドを設定します。複数のCMD
命令が存在する場合、最後の命令のみが有効になります。
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT
コンテナのエントリーポイントを定義し、実行可能ファイルとして実行できるようにします。コンテナを起動する際に--entrypoint
フラグを使用して上書きすることができます。
ENTRYPOINT ["python", "app.py"]
COPY
ホストシステムからイメージにファイルをコピーします。URLサポートやアーカイブの抽出などの高度な機能が必要でない限り、シンプルなファイル転送にはADD
ではなくCOPY
を使用することが推奨されています。
COPY . /app
ADD
ファイルをイメージに追加し、URLおよびアーカイブの抽出をサポートします。シンプルなファイルの転送にはCOPY
を優先することをお勧めします。
ADD https://example.com/file.tar.gz /app
ENV
イメージ内の環境変数を設定します。コンテナ内で実行されるプロセスからアクセスできます。
ENV APP_PORT=8080
EXPOSE
コンテナが特定のネットワークポートでリッスンすることをDockerに通知します。この命令はポートを公開するわけではありませんが、ドキュメントとして役立ちます。
EXPOSE 80
WORKDIR
後続の命令に対する作業ディレクトリを設定します。指定されたディレクトリが存在しない場合は作成されます。
WORKDIR /app
USER
後続の命令のためのユーザーを設定します。これは、コンテナ内で非ルートプロセスを実行する場合に役立ちます。
USER www-data
VOLUME
外部ストレージのマウントポイントを作成します。この命令は、コンテナで生成されたデータを永続化するために使用されます。
VOLUME /var/lib/mysql
カスタムイメージのビルド
Dockerfileを使用してカスタムイメージを作成することで、開発者は環境の設定、アプリケーションの構成、ソフトウェアの展開などのプロセスを効率化できます。この章では、ビルドプロセスについて説明します。
Dockerfileからカスタムイメージをビルドするには、ビルドコンテキスト(通常はカレントディレクトリ)に続いて、docker build
コマンドを使用します。
$ docker build -t your-image-name:tag .
-t
フラグは、新しいイメージに名前とオプションのタグを割り当てます。ビルドコンテキストには、Dockerfileおよびビルドプロセス中に必要な追加ファイルが含まれています。ビルドコンテキストは重要です。Dockerは、Dockerfileで参照されるファイルを探す場所として、ビルドコンテキストを使用します。
ビルドプロセスは次のステップで構成されています。
- DockerがDockerfileを読み取り、各命令を順番に処理する
- 各命令はイメージ内に新しいレイヤーを作成します。レイヤーは、後続のビルドを高速化するためにキャッシュされる
- 最終的なレイヤーは、新しいカスタムイメージを表し、コンテナを作成するために使用できる
例えば、単純なNode.jsアプリケーション用の次のDockerfileを考えてみます。
# ベースイメージを設定
FROM node:14
# 作業ディレクトリを設定
WORKDIR /app
# packageファイルをコピー
COPY package*.json ./
# 依存関係をインストール
RUN npm install
# アプリケーションコードをコピー
COPY . .
# アプリケーションのポートを公開
EXPOSE 3000
# アプリケーションを実行する
CMD ["npm", "start"]
このイメージをビルドする場合、Dockerは次のアクションを実行します。
- Docker Hubから
node:14
ベースイメージを取得 - 作業ディレクトリを
/app
に設定 package.json
およびpackage-lock.json
ファイルをイメージにコピーnpm install
を実行して、アプリケーションの依存関係をインストール- 残りのアプリケーションコードをイメージにコピー
- ポート3000を公開
- アプリケーションを
npm start
で実行するデフォルトコマンドを設定
イメージがビルドされたら、docker run
コマンドを使用してコンテナを作成および実行できます。
$ docker run -d -p 3000:3000 your-image-name:tag