はじめに
Railsなどを中心に勉強中のエンジニア初心者が他の記事を参考にしたり、実際に実装してみたりして、アウトプットの一環としてまとめたものです。
間違っていることもあると思われるので、その際は指摘いただけると幸いです。
Dockerfileとは
docker image
の設計図(Dockerfile
からdocker image
を作成する)。
他の人がDockerfile
を見たときに、どのようなコンテナが生成されるか一目瞭然となる
Instruction arguments
の形で記載していく。
Instruction
はdocker
に命令を送るコマンドで基本的には大文字で記述する(小文字でも動く)、arguments
は引数
Instruction:FROM
Dockerfile
の一番最初に記述する。
ベースとなるimage
を指定している。ここで指定したimage
の上に各Layer
が追加されていく。
基本的にはOS(ubuntu
やalpine
を選択する事が多い)を指定することになる。他の人が作成したimage
を指定することも可能。
ubuntu
は約70MBあるが、alpine
は5MBと軽量なのが特徴。必要最低限の機能を備えたimage
を取得する事が大切。
# Dockerfile
FROM ubuntu:latest
Instruction:RUN
右側にある文字列をLinux
コマンドとして実行する。
RUN
を使うことでコンテナを独自にカスタマイズする事ができる。
RUN
毎にimage layer
が重なっていく。RUN
を何度も実行してしまうと、docker image
の容量が大きくなってしまうため注意が必要。
# Dockerfile
FROM ubuntu:latest
RUN touch test
docker image
のLayer
数
Dockerfile
のベストプラクティスとしては、docker image
のLayer
数を最小限にする事が求められる(docker image
を小さくするため)。
Layer
を作るのはRUN
、COPY
、ADD
の3つのコマンドで、これらのコマンドを使うときは注意する。
コマンドを&&
で繋げて1回のRUN
で実行できるようにする(「 \ 」バックスラッシュで改行できる)
-y
オプションはパッケージをインストールする際のインタラクティブな質問にYESで答えることを意味する。
# Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
xxx \
yyy \
zzz
# インストールするパッケージはアルファベット順に並べると良い
ubuntu
でパッケージをインストールするにはapt-get
コマンド(またはapt
コマンド)を使う
$ apt-get update # 新しいパッケージリストを取得
$ apt-get install <package1> <package2> <package3> # <package>をインストール。半角スペースを空けてパッケージ名をつなげることで1回のapt-get installで実行可能
docker image
のcache
Dockerfile
からdocker image
をbuild
する時は、Layer
毎のcache
を用いる事ができる。
そのため、Dockerfile
の構成を検討する際はインストールする事が確定したパッケージのRUN
コマンドに新しいパッケージを追加して実行するのではなく、別のRUN
コマンドとして実行すると良い。
既に実行されているRUN
コマンドのLayer
に関しては、cache
を利用する事ができるためである。
Dockerfile
が完成した後に、まとめられるコマンドをまとめていくと良い(必ずまとめる)。
# Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
aaa \
xxx \
yyy \
zzz
# 確定したxxx,yyy,zzzのRUNコマンド内に新しくaaaを追加してしまうと、
# 既にあるxxx,yyy,zzzのLayerは無視され、新しいLayerが構築されてしまう
Instruction:CMD
コンテナのデフォルトのコマンドを指定する。コンテナを起動したときに最初に実行されるコマンドとなる。
CMD[””executable, “”param1, “param2”]
という構文をとり、原則Dockerfile
の最後に記述する。
実行したいコマンドがない場合は”/bin/bash”
とするのが一般的。
CMD
がないとFORM
で取得してきているimage
のデフォルトコマンドが実行されるが、何が実行されるか不明なため、CMDで実行コマンドを記述するようにした方がわかりやすい。
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
curl \
cvs \
nginx
CMD ["/bin/bash"]
RUN
とCMD
について
RUN
はLayer
を作るが、CMD
はLayer
を作らないという違いがポイントとなる。
docker image
のLayer
に持っておきたい場合はRUN
で記載する。
build context
およびdocker deamon
について
docker build
を実行する際は、Dockerfile
を指定するのではなく、Dockerfile
が存在しているディレクトリ(「.」カレントディレクトリ)を指定する。
docker build
を実行すると、指定されたディレクトリがdocker deamon
に渡され、docker deamon
が渡されたディレクトリとそのディレクトリ内のDockerfile
を基にdocker image
を作る。
このディレクトリのことをbuilde context
という(build
時にbuild context
内のファイルを活用する事ができる)。
docker context
内には不要なファイルなどは配置しないようにする事が望ましい。
docker build
を実行するクライアント側と、docker deamon
が存在するDocker
ホスト側が同一PC内であれば、build context
の容量が大きくとも通信時間はあまりかからないが、同一PC内に存在しない場合はREST API
で通信するため時間がかかってしまう恐れがある。
builde context
内のファイルをdocker image
に反映させるためには、ADD
やCOPY
というINSTRUCTIONが必要になる(Image Layer
として反映される)。
Instruction:COPY
build context
内のDockerfile
以外のファイル(またはディレクトリ)をdocker image
に組み込んで、最終的にはコンテナで使う事ができる。
# Dockerfile
FROM ubuntu:latest
RUN mkdir /new_dir
COPY something /new_dir
# COPY <src> <dest>
Instruction:ADD
tar
の圧縮ファイルを解凍したい場合はADD
を使用する。tar
ファイルをdocker image
に渡した際に自動で解凍まで実行してくれる。
ファイル容量(フォルダ容量)が大きいファイルをdocker image
に送る場合は、圧縮してから送信することになるため、ADD
を使用するとよい。
# Dockerfile
FROM ubuntu:latest
ADD compressed.tar /
# ADD <src> <dest>
Dockerfile
という名のファイルがbuild context
に存在しない場合
Dockerfile
を開発用(Dockerfile.dev
)とテスト用(Dockerfile.test
)など複数用意しておく場合がある。
そのような場合は下記のようなコマンドで実行する。
$ docker build -f <Dockerfile_name> <build context>
Instruction:ENTRYPOINT
ENTRYPOINT
を使用してデフォルトで実行するコマンドを定義することができる。
特徴としては、docker run
時に別のコマンドを実行させる事ができなくなる(コマンドの上書きが不可能)。
また、ENTRYPOINT
を使用した場合は、CMD
はオプションを定義する役割となる。
docker
のコンテナをコマンドのように扱いたい場合はENTRYPOINT
を使用する事がある。
# Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
curl \
cvs \
nginx
CMD ["ls", "--help"]
# デフォルトでlsコマンドを実行し、さらに--helpをオプションとして付けている
$ docker run <image> pwd
# デフォルトで実行するコマンドがCMDで定義されている場合は、実行するコマンドの上書きが可能
# Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
curl \
cvs \
nginx
ENTRYPOINT ["ls"]
CMD ["--help"]
# デフォルトでlsコマンドを実行するように定義している(コマンドの上書きは不可能)
# CMDで--helpをオプションとして指定している
$ docker run <image> pwd
# デフォルトで実行するコマンドがENTRYPOINTで定義されている場合は、実行するコマンドの上書きが不可能(エラーになる)
$ docker run <image> -la
# オプションに関しては、上書きが可能
Instruction:ENV
Dockerfile
で環境変数を設定する際に使用する(環境変数:OSの上で動くあらゆるプロセスが情報を共有するための変数)。
# Dockerfile
FROM ubuntu:latest
ENV key1 value
ENV key2=value
ENV key3="v a l u e" key4= v\ a\ l\ u\ e
ENV key5 v a l u e
Instruction:WORKDIR
Docker Instruction
を実行するディレクトリを変更する際に使用する。
WORKDIR <絶対path>
というように記述する。
WORKDIR
で指定したディレクトリが存在しない場合は、そのディレクトリが自動で作成されるため、mkdir
などでディレクトリを作成する必要はない。
# Dockerfile
FROM ubuntu:latest
RUN mkdir sample_folder
RUN cd sample_folder
RUN touch sample_file
# RUNコマンドは基本的にはルート直下で実行されるため、上記のようにcdコマンドでsample_folderに移動しても、「touch sample_file」はルート直下で実行される
# Dockerfile
FROM ubuntu:latest
RUN mkdir sample_folder && \
cd sample_folder && \
touch sample_file
# 上記のように&&でコマンドを繋げた場合は、「touch sample_file」は「sample_folder」配下に作られる。
# Dockerfile
FROM ubuntu:latest
WORKDIR /sample_folder
RUN touch sample_file
# 上記の状態でコンテナに入ると。「sample_folder」にいることになる(WORKDIRで「sample_folder」を指定して以降、戻るコマンドを実行していないため)
最後に
いかがでしたでしょうか。
今回はDockerfileを記載するためのコマンドについてまとめてみました。
ここ違うよ!でしたり、こうした方がいいよ!などがあればコメントいただけると幸いです。
他にも下記のような記事を投稿しております。
興味がありましたら、ぜひご覧ください。