これまでは、Dockerfileの中に記載された内容だけでDocker imageを作成してきましたが、Docker daemon や、build contextについて学習し、docker buildについて、さらに理解を深めました。
今回もかめ@usdatascientistさんの「米国AI開発者がゼロから教えるDocker講座」をUdemyで受講しながら進めています。
とても分かりやすく解説いただけますし、ハンズオン形式で講座が進むので、まさに「手で覚える」ことができるので、おすすめです!
www.udemy.com
では、振り返っていきたいと思います。
Docker daemonとbuild contextについて学ぶ
1.Dokcer daemonとbuild contextについて
これまで、DockerfileにDocker imageを作成するINSTRUCTION(命令)等を記載して、docker buildを実行する際は、引数にDockerfile自体ではなく、Dockerfileの入ったディレクトリを指定してきました。
これは、docker build実行時にDockerfileだけではなく、そのディレクトリ内にある他のファイルも使ってDocker imageを作成します。この、ディレクトリ内の「状況」を「built context」といいます。
また、build contextを受け取って、Docker imageを作成する役割を担っているのが、Docker daemonになります。
実際にこれまで、doker buildを実施してきたときに以下のように「Sending build context to Docker daemon」と表示されていて、contextをDocker daemonに受け渡していたことが確認できます。
上記の場合は、Dockerfileだけしかディレクトリに入っていなかったので、「2.048kB」のデータを受け渡すだけですんでいますが、このディレクトリ内に不要なファイルが入っていると、受け渡す容量がそれだけ大きくなりますので、このディレクトリ内には、必要最小限のファイルだけにしておく必要があります。
2.build context内のファイルをDocker imageに取り込む(COPY)
build contextのディレクトリ内にあるファイルをDocker imageに取り込むためには、COPYというINSTRUCTION(命令)を使います。
では、build contextのディレクトリに「something」ファイルを作成して、このファイルをDocker image内のディレクトリにコピーします。
以下の内容を記述したDockerfileを作成します。
COPYについては、arguments(引数)に、コピーしたいホスト側のファイルと、Docker image側のコピー先を指定します。今回は、コピー先のディレクトリをあらかじめ、RUNを使って作成(mkdir)しておきます。
FROM ubuntu:latest
RUN mkdir /new_dir
COPY something /new_dir/
docker buildを実行する前に、まず、ディレクトリ内のファイルを確認します。
ls
これらのファイルがdocker buildを実行した際にDocker daemonに受け渡されます。
では、buildしていきます。
docker build .
無事、Step3でCOPYも実行されて、Docker imageが作成できました。
次に、作成したDocker imageからコンテナを立ち上げて、「something」がコンテナ内にコピーされていることを確認します。
docker run -it a4be1c8a525e bash
ls /new_dir/
無事、build contextのディレクトリ内の「something」を、コンテナ内のディレクトリにコピーすることができました。
これで、事前に作成したファイルを、コンテナ内に持ち込むことができるようになりました。
3.build context内のtarファイルをDocker imageに取り込む(ADD)
今度は、単にbuild context内のファイルをコピーするのではなく、build context ディレクトリ内の圧縮ファイル(tarファイルなど)を、コピーして解凍するためにはADDというINSTRUCTION(命令)を使用します。
これは、build contextをDocker daemonに受け渡す際に、圧縮した状態のままで受け渡すことができますので、送信にかかる時間を短縮することができます。
では、試しに「hello」というファイルが入った「sample_folder」というディレクトリを圧縮した「compressed.tar」というファイルを、Docker image内に解凍するためには、以下のDockerfileを作成します。
ADDは、arguments(引数)に、解凍したいホスト側の圧縮ファイルと、Docker image側の解凍先を指定します。今回は解凍先にルートディレクトリを指定します。
FROM ubuntu:latest
ADD compressed.tar /
docker buildを実行する前に、まず、ディレクトリ内のファイルを確認します。
ls
では、buildしていきます。
docker build .
無事、Step2でADDが実行できました。
次に、作成したDocker imageからコンテナを立ち上げて、「compressed.tar」が解凍され、「sample_folder」が作成されていることを確認します。
docker run -it 4bfdf382a056 bash
ls /sample_folder/
無事、「compressed.tar」が解凍され、「sample_folder」ディレクトリと、その中に「hello」というファイルができていることが確認できました。
4.Dockerfileがbuild context以外にある場合
これまで、Dockerfileは、必ずbuild contextのディレクトリ内に配置してきました。
しかし、Dockerfileを切り替えながら使っていきたい場合に、build contextのディレクトリ内にDockerfileをいちいち入れ替えていると面倒です。このような時に、Dockerfileをbuild contextのディレクトリ以外に、複数のDockerfileを作成し、docker build時に指定できると便利になります。
では、実際にDockerfileを指定して、docker build を実施していきたいと思います。
今回は、Dockerfileを図10のように、build contextのディレクトリの親ディレクトリに保存します。
Dockerfileには、以下を記載しました。
ubuntu のDocker imageに、「hogehoge」というファイルを作成して、bashを立ち上げるDockerfileになります。
FROM ubuntu:latest
RUN touch hogehoge
CMD ["/bin/bash"]
Dockerfileを指定して、docker build を実行するためには、「-f」オプションを使って、Dockerfileを指定します。「..」は、親ディレクトリを表し、「.」は、カレントディレクトリ(現在いるディレクトリ)を表します。
docker build -f ../Docerfile .
無事、Docker imageが作成できました。
この方法を使うと、build contextのディレクトリと、Dockerfileの組み合わせを変えてdocker buildを行うことができます。
5.コンテナをコマンドのように引数を渡して使いたい(ENTRYPOINT)
DockerfileにCMDでコマンドを実行した場合は、docker runを実行してコンテナを起動した時に、CMDで指定したコマンドか、docker runで引数として渡したコマンドのどちらかのコマンドが実行され、CMDで指定したコマンドに引数を渡すことはできません。
例えば以下の通りDockerfileで、Docker imageを作成した場合
From ubuntu:latest
RUN touch hogehoge
CMD["ls"]
docker runで実行できるのは、以下の通りです。
docker run -it [Docker image ID]
→ この場合は、CMDのコマンド(ls)が実行される
docker run -it [Docker image ID] pwd
→ この場合は、引数に渡したコマンド(pwd)が実行される
docker runの引数に、CMDのコマンド(ls)の引数は指定できず、いかのようには実行できません。
× docker run -it [Docker image ID] -la
上記のように、docker run を実行する際に、コマンドではなくDockerfileで指定したコマンドの引数だけを指定したい場合は以下のようにENTRYPOINTというINSTRUCTION(命令)を使用します。
このとき、ENTRYPOINTの引数には、実行するコマンドを指定して、CMDで、そのコマンドの引数を指定します。
こうすることで、docker runを実行した際に、ENTRYPOINTまでは、デフォルトで指定され、docker runで引数を渡す(CMDで指定した引数を上書きする)ことができます。
From ubuntu:latest
RUN touch hogehoge
ENTRYPOINT ["ls"]
CMD["--help"]
では、実際にコンテナを起動していきます。
まずは、Docker imageをbuildします。
docker build .
buildされたDocker imageからコンテナを起動します。
このとき、[ls]の引数として「-la」を指定してみます。
docker run -it 5aff4de5619b -la
無事、CMDで指定した[--help]オプションではなく、[-la]オプションが引数として渡され、カレントディレクトリにあるファイルの詳細情報が表示されました。
このようにコンテナを起動するときに、引数を渡してコマンドのように実行することができるようになりました。
6.Docker imageの環境変数を設定する(ENV)
DockerfileでDocker imageの環境設定をするためには、ENVというINSTRUCTION(命令)を使います。
ENVは、引数に環境変数名=設定する値と指定するか、環境変数の後にスペースを入れて設定値と指定することができます。
以下のようなDockerfileを作成して試していきます。
FROM ubuntu
ENV key1 value1
ENV key2=value2
では、試してみます。
docker build .
次にコンテナを立ち上げて、環境変数の状態を確認します。
docker run -it 2af76fdfc73f bash
envコマンドで、環境変数の一覧を確認する。
env
無事、key1にvalue1が、key2にvalue2が設定されていることが確認できました。
このようにENVというINSTRUCTION(命令)を使うことで、環境変数の設定もできました。
7.Dockerfile内のINSTRUCTIONの実行ディレクトリを指定する(WORKDIR)
Dockerfileに記載されたRUNや、CMDなどのINSTRUCTION(命令)は、何も指定しなければ、すべてルートディレクトリで実行されます。
例えば、ディレクトリを作成して、そのディレクトリ内でコマンドを実行したい場合は、WORKDIRというINSTRUCTION(命令)でディレクトリを指定して実行します。
以下のようなDockerfileを作成して試していきます。
FROM ubuntu:latest
RUN mkdir sample_folder
WORKDIR /sample_folder
RUN touch sample_file
では、試してみます。
docker build .
次にコンテナを立ち上げて、作成されたファイルを確認します。
docker run -it b062abc9c389 bash
WORKDIRで、ディレクトリを移動しているので、立ち上げ時のカレントディレクトリも、/sample_folderとなっています。
では、sample_folderファイルの中身を確認します。
ls /sample_folder/
無事、sample_folder内に[sample_file]が作成されていました。
これで、Dockerfile内でコマンドを実行する際のディレクトリを指定することができるようになりました。
今回の振り返りは以上になります。
今回、Docker daemonと、build context の仕組みを理解し、様々なINSTRUCTION(命令)を利用して、Dockerfileからコンテナ作成までのレパートリーが、かなり増強できたと感じました。
いろいろな、コンテナを作成して実際に手を動かしながら、自分のものにしてきたいと思います。
今回受講している「米国AI開発者がゼロから教えるDocker講座」では、もっと詳しくわかりやすくご説明いただけているので、ほんとうに良い勉強になります。
今後も、継続して受講して、もっと、Dockerを使いこなせるようになりたいと思います!
www.udemy.com
【過去記事】
2019年8月31日(土)にE資格を受験して、合格しました!
E資格対策として勉強の進め方や、参考書などをまとめました。
これから受験される方がいらっしゃいましたらご参考まで。
oregin-ai.hatenablog.com
2019年3月9日(土)にG検定を受験し、見事合格できました!
受験の体験記や勉強法などを別のブログにまとめました。
これから受験される方がいらっしゃいましたらご参考まで。
g-kentei.hatenablog.com
【E資格対策に使った参考書】