俺人〜OREGIN〜俺、バカだから人工知能に代わりに頑張ってもらうまでのお話

俺って、おバカさんなので、とっても優秀な人工知能を作って代わりに頑張ってもらうことにしました。世界の端っこでおバカな俺が夢の達成に向けてチマチマ頑張る、そんな小さなお話です。現在はG検定、E資格に合格し、KaggleやProbSpaceのコンペに参画しながら、Pythonや機械学習、統計学、Dockerなどの勉強中です。学習したことをブログにアウトプットすることで、自分の身に着けていきたいと思います。まだまだ道半ばですが、お時間がありましたら見て行ってください。

Docker daemonとbuild contextについて学ぶ(米国AI開発者がゼロから教えるDocker講座)

これまでは、Dockerfileの中に記載された内容だけでDocker imageを作成してきましたが、Docker daemon や、build contextについて学習し、docker buildについて、さらに理解を深めました。

今回もかめ@usdatascientistさんの「米国AI開発者がゼロから教えるDocker講座」をUdemyで受講しながら進めています。

とても分かりやすく解説いただけますし、ハンズオン形式で講座が進むので、まさに「手で覚える」ことができるので、おすすめです!

では、振り返っていきたいと思います。

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に受け渡していたことが確認できます。

f:id:kanriyou_h004:20200712201418p:plain

図1.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

f:id:kanriyou_h004:20200716204252p:plain

図2.build contextとして受け渡されるファイル

これらのファイルがdocker buildを実行した際にDocker daemonに受け渡されます。
では、buildしていきます。

docker build .

f:id:kanriyou_h004:20200716204908p:plain

図3.docker buildを実行する

無事、Step3でCOPYも実行されて、Docker imageが作成できました。

次に、作成したDocker imageからコンテナを立ち上げて、「something」がコンテナ内にコピーされていることを確認します。

docker run -it a4be1c8a525e bash

f:id:kanriyou_h004:20200716205320p:plain

図4.コンテナを立ち上げる

ls /new_dir/

f:id:kanriyou_h004:20200716205504p:plain

図5./new_dir/ディレクトリ内に「something」ができていることを確認する

無事、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

f:id:kanriyou_h004:20200716211818p:plain

図6.build context内のファイルを確認する

では、buildしていきます。

docker build .

f:id:kanriyou_h004:20200716212415p:plain

図7.docker buildを実行する

無事、Step2でADDが実行できました。

次に、作成したDocker imageからコンテナを立ち上げて、「compressed.tar」が解凍され、「sample_folder」が作成されていることを確認します。

docker run -it 4bfdf382a056 bash

f:id:kanriyou_h004:20200716212806p:plain

図8.コンテナを立ち上げる

ls /sample_folder/

f:id:kanriyou_h004:20200716213017p:plain

図9.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のディレクトリの親ディレクトリに保存します。

f:id:kanriyou_h004:20200717211912p:plain

図10.build contextのディレクトリの親ディレクトリにDockerfileを作成する

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 .

f:id:kanriyou_h004:20200717213257p:plain

図11.Dockerfile を指定してdocker buildを実行する。

 無事、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 .

f:id:kanriyou_h004:20200718201902p:plain

図12.docker buildを実行する

buildされたDocker imageからコンテナを起動します。

このとき、[ls]の引数として「-la」を指定してみます。

docker run -it 5aff4de5619b -la

f:id:kanriyou_h004:20200718202213p:plain

図13.docker run でENTRYPOINTで指定したコマンドに引数を渡す

無事、CMDで指定した[--help]オプションではなく、[-la]オプションが引数として渡され、カレントディレクトリにあるファイルの詳細情報が表示されました。

このようにコンテナを起動するときに、引数を渡してコマンドのように実行することができるようになりました。

6.Docker imageの環境変数を設定する(ENV)

DockerfileでDocker imageの環境設定をするためには、ENVというINSTRUCTION(命令)を使います。

ENVは、引数に環境変数名=設定する値と指定するか、環境変数の後にスペースを入れて設定値と指定することができます。

以下のようなDockerfileを作成して試していきます。

FROM ubuntu

ENV key1 value1

ENV key2=value2

では、試してみます。

docker build .

f:id:kanriyou_h004:20200718203817p:plain

図14.docker buildを実行する

次にコンテナを立ち上げて、環境変数の状態を確認します。

docker run -it 2af76fdfc73f bash

f:id:kanriyou_h004:20200718204001p:plain

図15.コンテナを立ち上げる

envコマンドで、環境変数の一覧を確認する。

env

f:id:kanriyou_h004:20200718204139p:plain

図16.環境変数の一覧を確認する

無事、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 .

f:id:kanriyou_h004:20200718210353p:plain

図17.docker buildを実行する

次にコンテナを立ち上げて、作成されたファイルを確認します。

docker run -it b062abc9c389 bash

f:id:kanriyou_h004:20200718210613p:plain

図18.コンテナを立ち上げる

WORKDIRで、ディレクトリを移動しているので、立ち上げ時のカレントディレクトリも、/sample_folderとなっています。

では、sample_folderファイルの中身を確認します。

ls /sample_folder/

f:id:kanriyou_h004:20200718210838p:plain

図19./sample_folder/の中身を確認する

無事、sample_folder内に[sample_file]が作成されていました。

これで、Dockerfile内でコマンドを実行する際のディレクトリを指定することができるようになりました。

 

今回の振り返りは以上になります。

今回、Docker daemonと、build context の仕組みを理解し、様々なINSTRUCTION(命令)を利用して、Dockerfileからコンテナ作成までのレパートリーが、かなり増強できたと感じました。

いろいろな、コンテナを作成して実際に手を動かしながら、自分のものにしてきたいと思います。

 

今回受講している「米国AI開発者がゼロから教えるDocker講座」では、もっと詳しくわかりやすくご説明いただけているので、ほんとうに良い勉強になります。

今後も、継続して受講して、もっと、Dockerを使いこなせるようになりたいと思います! 

px.a8.net

 

 【過去記事】

2019年8月31日(土)にE資格を受験して、合格しました!

E資格対策として勉強の進め方や、参考書などをまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

oregin-ai.hatenablog.com 

 

 2019年3月9日(土)にG検定を受験し、見事合格できました!

受験の体験記や勉強法などを別のブログにまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

g-kentei.hatenablog.com

 【E資格対策に使った参考書】

 

f:id:kanriyou_h004:20200714220856p:plain