Dockerfileの構成と使用方法

Dockerイメージの基礎知識

Dockerイメージは特別なファイルシステムであり、コンテナ実行時に必要なアプリケーション、ライブラリ、リソース、設定ファイルを含むだけでなく、匿名ボリューム、環境変数、ユーザーなどの実行時設定も含まれます。イメージは動的なデータを含まず、ビルド後に内容が変更されることはありません。

イメージのカスタマイズは各レイヤーに追加された設定やファイルをカスタマイズすることです。各レイヤーでの変更、インストール、ビルド、操作のコマンドをスクリプトに記述し、そのスクリプトを使ってイメージをビルド・カスタマイズすることで、再現性のない問題、ビルドの透明性、サイズの問題が解決します。このスクリプトがDockerfileです。

Dockerfileはテキストファイルで、複数の命令(Instruction)で構成されており、それぞれの命令は1つのレイヤーを構築します。Dockerfileがあることで、必要に応じて命令を追加または変更し、再度イメージを生成するだけで済み、コマンドを手入力する手間が省けます。

Dockerfileの命令一覧

1、FROM 基準イメージの指定

FROM命令は新しいイメージのビルドに使用する基準イメージを指定します。FROM命令はDockerfileの最初の命令でなければならず、ビルドプロセス開始後、Dockerはこのイメージを基に新しいイメージを構築します。

FROM命令の書式:

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>

指定できるイメージは任意の有効な基準イメージです。FROM命令には以下の制限があります:

  • FROM命令はDockerfile内の最初のコメント以外の命令でなければならない
  • Dockerfile内で複数のイメージを作成する場合、FROM命令は複数回使用可能。ただし、各FROM命令の前に前回のイメージIDを記録する必要がある
  • タグまたはダイジェストは省略可能で、指定しない場合はlatestバージョンを使用

2、RUN コマンドの実行

イメージビルド中に特定のコマンドを実行し、中間イメージを生成します。

#シェル形式
RUN <command>
#exec形式
RUN ["executable", "param1", "param2"]
  • RUN命令は現在のイメージ内で任意の有効なコマンドを実行し、実行結果をコミットします。コマンド実行後、次のDockerfile命令が実行されます。
  • レイヤーごとのRUN命令とコミットはDockerの核心理念に従ったものです。これにより、バージョン管理のように、任意の時点からイメージをカスタマイズできます。
  • RUN命令で作成された中間イメージはキャッシュされ、次回のビルドで使用されます。キャッシュを使いたくない場合は、--no-cacheオプションを指定してビルドします。

3、COPY ファイルのコピー

COPY <source path>... <destination path>
COPY ["<source path1>",... "<destination path>"]

RUN命令と同じく2つの形式があり、コマンド形式と関数呼び出し形式です。COPY命令はビルドコンテキストディレクトリのにあるファイルまたはディレクトリを新しいイメージ内のにコピーします。例えば:

COPY package.json /usr/src/app/

は複数指定可能で、ワイルドカードも使用できます。ワイルドカードはGoのfilepath.Match規則に従います。例えば:

COPY hom* /mydir/
COPY hom?.txt /mydir/

はコンテナ内の絶対パスか、ワークディレクトリからの相対パスです(ワークディレクトリはWORKDIR命令で指定)。目的パスは事前に作成されていなくても、存在しない場合はコピー前に作成されます。

さらに、COPY命令では元ファイルのメタデータ(読み取り権限、書き込み権限、実行権限、変更時間など)が保持されます。これはイメージカスタマイズに役立ちます。特にGitで管理されているファイルの場合に重要です。

4、ADD 高度なファイルコピー

ADD命令はCOPY命令とほぼ同じ形式と性質を持ちます。

Docker公式のDockerfileベストプラクティスでは、可能な限りCOPYを使用することを推奨しており、COPYは明確なコピー操作のみを意味するのに対し、ADDはより複雑な機能を持ち、動作が不確かな場合があります。ADDを使用すべきのは自動解凍が必要な場合のみです。

また、ADD命令はイメージビルドキャッシュを無効化するため、ビルド速度が遅くなる可能性があります。

したがって、COPYADDの選択原則としては、すべてのファイルコピーにはCOPYを使用し、自動解凍が必要な場合のみADDを使用します。

ビルド時にコンテキスト内のファイルをイメージ内にコピーする形式:

ADD <source path>... <destination path>
ADD ["<source path>",... "<destination path>"]

5、ENV 環境変数の設定

2つの形式があります:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

この命令は環境変数を設定するだけです。以降のRUN命令や実行中のアプリケーションでもこの定義された環境変数を使用できます。

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"

この例では改行方法とスペースを含む値を二重引用符で囲む方法を示しています。これはShellの動作と一致します。

6、EXPOSE ポートの公開

ビルドされたイメージのリッスンポートを設定します。形式:

EXPOSE <port> [<port>...]

EXPOSE命令はホスト側のポートをリッスンしません。リッスンするには、docker run時に-pまたは-Pパラメータを使用してコンテナポートをホストのポートに公開する必要があります。

7、VOLUME 匿名ボリュームの定義

VOLUMEはマウントポイントを作成し、イメージから生成されたコンテナにボリュームを追加します:

VOLUME ["/data"]

ボリュームは1つ以上のコンテナの指定ディレクトリに存在でき、共有可能です:

  • ボリュームはコンテナ間で共有・再利用可能
  • コンテナ間でボリュームを共有する必要はありません
  • ボリュームの変更は即座に反映される
  • ボリュームの変更はイメージに影響を与えません
  • ボリュームは使用しているコンテナがなくなるまで保持されます

VOLUMEにより、ソースコードやデータなどをイメージに含めつつ、コミットせずに複数コンテナ間で共有できます。

8、CMD コンテナ起動時のコマンド

コンテナ起動時に実行するコマンドを指定します。CMDには以下の3つの形式があります:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

実行ファイルを省略したexec形式では、CMDの引数はENTRYPOINTのデフォルト引数として扱われます。ENTRYPOINTもexec形式である必要があります。ENTRYPOINTとの組み合わせについてはENTRYPOINTを参照してください。

RUN命令との違い:RUNはビルド時に実行され新しいイメージを生成し、CMDはコンテナ実行時に実行され、ビルド時には何も行われません。

9、ENTRYPOINT エントリーポイント

コンテナ起動時に実行するコマンドを指定します。追加コマンドを指定できます。

ENTRYPOINTはコンテナのデフォルトプログラムを設定するために使用します。つまり、イメージからコンテナを作成するたびに、ENTRYPOINTで指定されたプログラムがデフォルトプログラムになります。ENTRYPOINTには以下の2つの形式があります:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

ENTRYPOINTはCMDと似ていますが、docker runで実行されるコマンドはENTRYPOINTを上書きせず、docker runで指定された引数はENTRYPOINTに渡されます。Dockerfileでは1つのENTRYPOINT命令のみが許可され、複数指定された場合は最後の命令のみが実行されます。

docker runで指定された引数はENTRYPOINTに渡され、CMDで指定された引数を上書きします。例えば、docker run <image> -dを実行すると、-d引数はエントリーポイントに渡されます。

docker run --entrypointでエントリーポイントを上書きすることも可能です。例えば、次のようにコンテナの実行プログラムを指定できます:

ENTRYPOINT ["/usr/bin/nginx"]

10、USER 現在のユーザーの指定

イメージ実行時に使用するユーザーを指定します:

USER daemon

USERで指定されたユーザーは、ユーザー名、UID、GID、またはその組み合わせを使用できます。以下はすべて有効な指定方法です:

USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

USERで指定されたユーザーは、Dockerfileの以降の命令(RUN、CMD、ENTRYPOINT)で使用されます。イメージビルド完了後、docker runでコンテナを実行する際は-uパラメータでユーザーを上書きできます。

11、WORKDIR コンテナ内の作業ディレクトリの指定

コンテナ内の作業ディレクトリを設定します:

WORKDIR /path/to/workdir

WORKDIRで設定されたディレクトリ以降、DockerfileのRUN、CMD、ENTRYPOINT、ADD、COPYなどの命令はこのディレクトリで実行されます。例えば、WORKDIRで作業ディレクトリを設定:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

この例では、pwdは/a/b/cディレクトリで実行されます。docker runでコンテナを実行する際は-wパラメータで作業ディレクトリを上書きできます。

12、LABEL イメージのメタデータの追加

LABELはイメージにメタデータを追加するために使用します。メタデータはキーと値のペアで指定します:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

LABELでメタデータを指定する際、1つのLABELで1つ以上のメタデータを指定できます。複数のメタデータを指定する場合はスペースで区切ります。多くの中間イメージを生成しないように、すべてのメタデータを1つのLABEL命令で指定することを推奨します。例えば:

LABEL version="1.0" description="Webサーバー" by="Docker筆録"

指定後はdocker inspectで確認できます:

docker inspect itbilu/test
"Labels": {
    "version": "1.0",
    "description": "Webサーバー",
    "by": "Docker筆録"
},

13、ARG ビルドパラメータ

ARGはビルド時に渡す変数を指定します:

ARG <name>[=<default value>]

例えば、2つの変数をARGで指定:

ARG site
ARG build_user=IT筆録

上記ではsiteとbuild_userの2つの変数を指定し、build_userにはデフォルト値が設定されています。docker buildでイメージをビルドする際は、--build-arg <varname>=<value>パラメータでこれらの変数の値を指定または再設定できます。

docker build --build-arg site=itiblu.com -t itbilu/test .

このようにしてitbilu/testイメージをビルドし、siteはitbilu.comに設定され、build_userはデフォルト値のIT筆録になります。

14、ONBUILD イメージトリガーの設定

ONBUILDはイメージのトリガーを設定するために使用します:

ONBUILD [INSTRUCTION]

ビルドされたイメージが他のイメージのベースイメージとして使用される場合、そのイメージのトリガーが発動します。例えば、イメージが使用される際に何か処理を行う場合:

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

15、STOPSIGNAL コンテナ停止時のシグナル

コンテナ停止時に送信するシステムコールシグナルを設定します:

STOPSIGNAL signal

使用するシグナルはカーネルシステムコールテーブルの有効な値でなければなりません。例:SIGKILL。

16、SHELL命令

SHELLはコマンド(シェル形式)の実行に使用するデフォルトシェルタイプを設定します:

SHELL ["executable", "parameters"]

SHELLはWindows環境で特に有用です。Windowsでは通常cmdとpowershellの2つのシェルがあり、さらにshもあります。この場合、SHELLで使用するシェルタイプを指定できます:

FROM microsoft/windowsservercore

# cmd /S /C echo defaultとして実行
RUN echo default

# powershell -command Write-Host defaultとして実行
RUN powershell -command Write-Host default

# powershell -command Write-Host helloとして実行
SHELL ["powershell", "-command"]
RUN Write-Host hello

# cmd /S /C echo helloとして実行
SHELL ["cmd", "/S", "/C"]
RUN echo hello

Dockerfileのファイル形式

## Dockerfileの形式

# このdockerfileはubuntuイメージを使用します
# VERSION 2 - EDITION 1
# 著者: docker_user
# 命令形式: Instruction [arguments / command] ..

# 1、最初の行は必須で、ベースイメージ情報を指定
FROM ubuntu

# 2、メンテナー情報
MAINTAINER docker_user docker_user@email.com

# 3、イメージ操作命令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# 4、コンテナ起動実行命令
CMD /usr/sbin/nginx

Dockerfileは4つの部分に分けられます:ベースイメージ情報、メンテナー情報、イメージ操作命令、コンテナ起動実行命令。最初はベースイメージ名を指定する必要があります。その後は一般的にメンテナー情報を記載します。次にRUN命令などのイメージ操作命令が続きます。各RUN命令は新しいレイヤーを追加し、コミットします。最後にCMD命令でコンテナ実行時の操作コマンドを指定します。

Dockerfileの例

[root@localhost ~]# cd /opt/
[root@localhost opt]# mkdir nginx   ## Nginxディレクトリを作成
[root@localhost opt]# cd nginx/
[root@localhost nginx]# vim Dockerfile

FROM centos:7
MAINTAINER Nginxです <Gerry>
RUN yum install -y proc-devel gcc gcc-c++ zlib zlib-devel make openssl-devel wget && wget http://nginx.org/download/nginx-1.21.1.tar.gz
ADD nginx-1.21.1.tar.gz /usr/local
WORKDIR /usr/local/nginx-1.21.1/
RUN ./configure --prefix=/usr/local/nginx && make && make install
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;">>/usr/local/nginx/conf/nginx.conf
WORKDIR /root/nginx
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
[root@localhost nginx]# vim run.sh

#!/bin/bash
/usr/local/nginx/sbin/nginx   ## Nginxサービスを開始
[root@localhost nginx]# mount.cifs //192.168.100.3/LNMP-C7 /mnt/  ## イメージをマウント
パスワード:  
[root@localhost nginx]# cp /mnt/nginx-1.12.2.tar.gz ./   ## 現在のディレクトリにコピー
[root@localhost nginx]# docker build -t nginx:new .   ## イメージを作成
[root@localhost nginx]# docker run -d -P nginx:new    ## コンテナを作成
228c1f5b8070d52c6f19d03159ad93a60d682a586c0b1f944dc651ee40576a3e
[root@localhost nginx]# docker ps -a   ## コンテナを表示
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS                                           NAMES
228c1f5b8070        nginx:new           "/run.sh"                9 seconds ago       Up 8 seconds                  0.0.0.0:32770->80/tcp, 0.0.0.0:32769->443/tcp   busy_booth
## ブラウザでアクセス<br></br><br></br><strong>Dockerfileのテスト</strong><br></br><strong>ビルドパラメータのデフォルト値はlatest ARG VERSION=latest</strong><br></br><strong>パラメータに基づいてnginxバージョンをビルド</strong><br></br><strong>FROM nginx:${VERSION}</strong><br></br><strong>ポート80を公開</strong><br></br><strong>EXPOSE 80</strong><br></br>

ARG VERSION=latest FROM nginx:${VERSION} EXPOSE 80

ビルド開始

-t はタグの意味

--build-arg はビルドパラメータの意味

-f はdockerfile名を指定する(ここでは同じ名前)

. は現在のコンテキスト

docker build -t mynginx:v2 --build-arg VERSION=latest -f dockerfile .

複数パラメータの場合、CMDは実行時に実行され、複数のCMDは最後の1つだけが実行されます。

Dockerfileの内容

ARG VERSION=latest ARG USER=aaa FROM nginx:${VERSION} EXPOSE 80 CMD echo h1 CMD echo h2

docker build -t mynginx1 --build-arg VERSION=latest --build-arg USER=ccc -f dockerfile .

タグ: Docker Dockerfile コンテナ イメージ ビルド

5月28日 04:54 投稿