0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

初心者向け DockerFile の基礎知識

Last updated at Posted at 2021-06-26

背景

環境構築を楽にするために、docker の勉強をしております。
今回は DockerFile について勉強したので記事にしました。
似たような命令の違いなど記述しているので、参考になれば嬉しいです。

DockerFile

以下を参考にして記事を作成しております。

DockerFile とは

イメージを作成するために実行するコマンドを記述するファイルです。
Docker は Dockerfile から命令を読み込んで、自動でイメージをビルドします。

DockerFile を利用するメリット

イメージの作り方としては DockerFile から作成するか、コンテナをカスタマイズしてイメージ化するかの2つがあります。

コンテナをカスタマイズしてイメージ化するのは、DockerFile を学習するコストはありませんが、どのようなイメージなのかが分かりにくいです。

DockerFile を使うことでイメージで実行された命令が DockerFile を見ることで簡単にわかるため、どのようなイメージなのか分かります。
さらに GitHub などで DockerFile を管理すると変更点も分かります。

記述書式

コメントの付け方

#をつけることで#以降の同行の文字列をコメントとして記述することができます。

# Apache のインストール
RUN yum install -y httpd

パーサ・ディレクティブ

#をつけるとコメント化されると書きましたが、例外があります。
以下のように DockerFile 内のエスケープ文字を指定する場合のみ、コメントとして扱いません。

# escape=\

現在(2021/06/26)では、パーサディレクティブとして扱うのはescapeのみです。

命令(instruction)

大文字、小文字の区別はしませんが、大文字での記述を推奨しております。

ベースイメージの指定(FROM)

イメージのベースとなるイメージを指定します。
DockerFile は基本的にFROM命令から始まります。

記述は以下のように行います。

FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]

記述例

FROM centos:centos7

コマンドの実行(RUN)

様々なコマンドの実行ができます。
頻繁に使う命令です。

記述は以下のように行います。

RUN <command> (シェル形式、コマンドはシェル内で実行される、シェルとはデフォルトで Linux なら /bin/sh -c、Windows なら cmd /S /C)

デフォルト以外のシェルを使用したいときは以下のように記述します。

RUN /bin/bash -c 'echo hello'
RUN ["/bin/bash", "-c", "echo hello"]

記述例

RUN yum install -y httpd

exec形式で記述する場合は、"を使いましょう。
json配列扱いなので、'は使えません。

コンテナ実行時の処理の記述(CMD, ENTRYPOINT)

コンテナの実行時の処理を設定することができます。
CMDはデフォルト処理の設定、ENTRYPOINTは必ず実行される処理の設定です。
言葉だけでは分かりにくいと思うので、具体例を交えて説明していきます。

CMDの記述は以下のように行います。

CMD ["executable","param1","param2"] (exec 形式、この形式が推奨される)
CMD ["param1","param2"] ( ENTRYPOINT のデフォルト・パラメータとして)
CMD command param1 param2 (シェル形式)

ENTRYPOINTの記述は以下のように行います。

ENTRYPOINT ["executable", "param1", "param2"] (exec 形式、この形式が推奨される)
ENTRYPOINT command param1 param2 (シェル形式)

ここから、CMDENTRYPOINTの違いについて説明します。

以下の命令を持つコンテナを作成した場合を考えます。

ENTRYPOINT ["wget"]
CMD ["https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.25.tar.gz"]

コンテナ起動時に mysql のソースコードをダウンロードするコンテナが作成されます。
この場合、ENTRYPOINTで指定しているwgetは必ず実行されます。
しかし、CMDで指定されているURLはdocker run時に引数が指定されなかった場合のみ適用されます。

# この場合は wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.25.tar.gz が実行される。
docker run イメージ名 

# この場合は wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.20.tar.gz が実行される。
docker run イメージ名 https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.20.tar.gz

このようにデフォルト処理か必ず実行される処理かの違いがあります。

イメージにメタ情報付与(LABEL)

イメージに対してメタデータを付与します。
LABELではキーバリューペアによる記述を行います。
値に空白などを含める場合は、クォートとバックスラッシュを用います。

以下のように記述します。

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

FROMで使用しているベースイメージのラベルのメタ情報も作成するイメージに付与されます。
ラベルのキーが一致した場合は新しく指定したメタ情報に書き換えられます。

docker inspectでメタ情報を見ることができます。

コンテナがリッスンするポートの指定(EXPOSE)

コンテナの実行時に、所定ネットワーク上のどのポートをリッスンするかを指定します。
EXPOSEだけでは意味がなくて、docker run 時に -P オプションを記述することによって、EXPOSEで指定したコンテナ側のポートとホスト側の空いているポートがポートフォワーディングされます。

以下のように記述します。

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

個人的には-p ホスト側のポート:コンテナ側のポートで指定して起動することが多いです。

環境変数、変数の定義(ENV, ARG)

ENVはコンテナの環境変数 <key><value> という値を設定します。
ARGはDockerFile内の変数 <name><default value> という値を設定します。
ENVARGの違いとして、ENVはコンテナ作成後も環境変数として定義されますが、ARGはイメージをビルドする際に一時的に定義される変数であるため、作成後のコンテナには定義されません。

以下のように記述します。

ENV <key> <value>
ENV <key>=<value> ...

ARG <name>[=<default value>]

記述例

ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy

ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

# 定義してdocker run で値を設定することもできる。
ARG user
ARG user=hoge

コンテナ内にファイルを配置(ADD, COPY)

<src> に示されるファイル、ディレクトリをコピーして、イメージ内のファイルシステム上のパス<dest> に加えます。

DockerFile を配置しているディレクトリ(コンテキストディレクトリ)、またはコンテキストディレクトリ配下にあるディレクトリのファイルを配置することができます。

以下のように記述します。

ADD <src>... <dest>
ADD ["<src>",... "<dest>"] (この書式はホワイトスペースを含むパスを用いる場合に必要)

COPY <src>... <dest>
COPY ["<src>",... "<dest>"] (パスにホワイトスペースを含む場合にこの書式が必要)

ADDCOPYの違いは以下の通りです。

ADDは以下の書式でリモートURLからファイルをダウンロードできます。

ADD https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.25.tar.gz 配置先

また、ADD<src> がローカルのtarアーカイブであり、認識できるフォーマット(gzip、bzip2、xz)である場合、tarアーカイブが自動で展開されます。
リモートURLからのダウンロードである場合は展開されません。

ボリュームを作成後、マウント(VOLUME)

指定された名前を使ってマウントポイントを生成し、ホスト側に作成されたボリュームにマウントします。

以下のように記述します。

VOLUME ["/data"]
VOLUME /var/log /var/db 

個人的な感想ですが、このような形でボリュームを作成するとVOLUME NAMEがハッシュ値になってしまい、よくわからなくなってしまうのでボリュームを作成してdocker run -vを使ってマウントしたほうが良いかと思います。

命令実行を行うユーザの指定(USER)

イメージが実行される際にUSER以降の命令の実行ユーザを指定します。

以下のように記述します。

USER <user>[:<group>]
USER <UID>[:<GID>]

ワークディレクトリの指定(WORKDIR)

コマンドを実行するディレクトリ(ワークディレクトリ)を指定します。
相対パス、絶対パス、どちらでも指定可能ですが、相対パスで指定した場合は、指定前のワークディレクトリからの相対パスになります。

以下のように記述します。

WORKDIR /path/to/workdir

DockerFile 記述例

Apache をインストールして実行するイメージの記述例です。

# ベースイメージの指定
FROM centos:centos7

# Apache のインストール
RUN yum install -y httpd

# Apache の起動
ENTRYPOINT ["/usr/sbin/httpd", "-DFOREGROUND"]

最後に

冒頭にもお話ししましたが、DockerFile は非常に便利です。
この記事は知識定着のためのアウトプットですが、私のような docker 初心者の方の助けになると嬉しいです。

最後まで読んでいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?