【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その3:Dockerfileってなに? 〜

コンテナ・Docker

こんにちは、サイオステクノロジー技術部 武井(Twitter:@noriyukitakei)です。今回は前回に引き続き、Dockerfileについて、世界一わかりみが深い説明をしていこうと思っております。

7回シリーズでお届けする予定で、今回は第3回目となります。

  1. その1:コンテナってなに?
  2. その2:Dockerってなに?
  3. 今回はこちら → その3:Dockerfileってなに?
  4. その4:docker-composeってなに?
  5. その5:Dockerのネットワークってどうなってるの?
  6. その6:Dockerのファイルシステムってどうなってるの?
  7. その7:実践!!Dockerでアプリケーション開発!!(執筆中)

Dockerfileとは?

Dockerfileとは、Dockerのイメージを作成する際に実行するコマンドをコード化して、一つのファイルにまとめたものです、、、という説明ではいまいちピンとこないのではないかと思います。そこで、Dockerfileを使わない場合と、使った場合で何がどのように嬉しくなるのかを説明したいと思います。

Dockerfileを使わない場合

前回の「【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その2:Dockerってなに? 〜 」のブログで、CentOSのDockerコンテナを作成する例を示しました。

でも実際は、このまま利用する人は少ないだろうと思います。このイメージをベースに色々なツールを入れたいですよね。ここでは以下のユースケースを考えてみます。

CentOSにApacheとPHPをインストールし、簡単なPHPアプリをコピーしてApacheを起動する。

これをDockerfileを使わない方法で実施してみます。

※ PHPのOfficialイメージを利用すればラクチンで実現できますが、ここでは説明のためにあえて、面倒な方法でやっていますm(_ _)m

まずはCentOS7のイメージからtestwebというコンテナを作成してデーモンとして起動し、ローカルの8080にアクセスしたらコンテナの80にポートフォワードされるようにします。

 

コンテナにログインします。

 

Apacheをインストールします。

 

phpをインストールします。

 

Apacheを起動します。

 

コンテナから抜けます。

 

以下のようなPHPファイルを作成します。

 

コンテナにコピーします。

 

http://localhost:8080/test.phpにアクセスして、以下ような画面が表示されれば成功です。

いかがでしたでしょうか?まんどくさー。わざわざコンテナ立ち上げるたびにこんなことしたくないですよね。エンジニア的には自動化したいという気持ちが沸々と湧き上がると思います。そんな悩みを解決してくれるのがDockerfileです。

Dockerfileを使う場合

まずは実践!!

では、先程のまんどくさいことと同じことをするDockerfileを作ってみます。Dockerfileを使うと先程の手順を全て自動化することができます。説明は後ほどしますので、まずは手を動かしてやってみて下さい。

以下のDockerfileを作成します。ファイル名はDockerfileとして下さい。

 

先程作成したDockerfileのあるディレクトリで以下のコマンドを実施して下さい。

 

新しいイメージができているのが確認できます。

 

先程のイメージからコンテンツを作成します。

 

http://localhost:8080/test.phpにアクセスしますと先程と同じ結果になると思います。

何が起きたのでしょうか?

結果は「Dockerfileを使わない場合」と同じですが、その手順はかなり短縮されたことが実感できたかと思います。Dockerfileというファイルを作成して、それをdocker buildというコマンドに食わせたということはなんとなく想像はつくかと思いますが、本章ではこれをより詳しく解説したいと思います。今回Dockerfileを使って行った作業のイメージは以下のとおりです。

上図の通りその大まかな手順は以下のとおりです。

  1. Dockerfileを作成
  2. docker buildコマンドでDockerfileを元にイメージを作成
  3. 作成したイメージを元にコンテナを起動

ではひとつずつ解説したいと思います。

1.Dockerfileを作成

Dockerfileとは、Docker Hubから取得したイメージに対して実施したいコマンドを書いたものです。先程作成したDockerfileを再び見てみましょう。

 

では、一つずつ解説していきます。

これは、FROMで指定したDockerイメージをベースに、これから記述するコマンドを実施しますよという意味です。今回の例ではCentOS7のイメージをベースに、様々なコマンドを実行するという意味になります。このFROMで指定したイメージをベースイメージと呼びます。

 

FROMで指定したイメージに対してコマンドを実行するためにはRUNを使います。このケースでは、ApacheとPHPをインストールします。

 

COPYは、ローカルにあるファイルをイメージ上にコピーします。この場合は、test.phpを/var/www/htmlディレクトリにコピーします。

 

CMDはコンテナ起動時に実行するコマンドを指定します。[]で囲って記述して、その中に配列みたいに入れていきます。1つ目実行するコマンド、2つ目以降はコマンドの引数を入れていきます。この例ではApacheを起動しています。

ここで、疑問に思った方がいらっしゃるかと思いますが、RUNもCOPYもCMDもコマンドを実行するものです。では、その違いはなんでしょうか?それは実行タイミングの違いです。イメージにしてみました。

 

RUNやCOPYコマンドはベースイメージであるCentOSから、新たなイメージであるtestphpimgを作成するとき、そのイメージに対して実行されます。つまり、CentOSのイメージに対して「RUN yum -y install httpd php」「COPY test.php /var/www/html/」が実行されたものがtestphpimgになります。

CMDコマンドは、出来上がったtestphpimgイメージからコンテナを生成するときに一度だけ実行されるコマンドになります。

この例で言えば、ApacheやPHPのインストールがインストールされ、test.phpがコピーされたものがtestphpimgになります。そして、testphpimgからコンテナを起動するたびにApacheが起動されます。

2.docker buildコマンドでDockerfileを元にイメージを作成

次に1で作成したDockerfileを元にApache、PHPがインストールされ、実行したPHPファイルtest.phpを含むイメージを作成します。そのためにはdocker buildコマンドを使います。その書式が以下のとおりです。

docker build -t  [イメージ名] :[タグ名]  [Dockerfileのあるディレクトリ]

※ タグ名は省略可能

上記のコマンドは、[Dockerfileのあるディレクトリ]にあるDockerfileをもとに、[イメージ名]で指定したDockerイメージを作成します。ではdocker buildコマンドを使って、「Dockerfileを使わない場合」と同じ動作をするコンテナのDockerイメージを作ってみます。先程作成したDockerfileのあるディレクトリで以下のコマンドを実施して下さい。

 

するとtestphpimgというイメージができているのが確認できます。タグ名を指定しないと自動的にlatestというタグ名が付与されます。

3.作成したイメージを元にコンテナを起動

では、先程作成したイメージを元にコンテナを起動してみます。

これはご存知のdocker runコマンドです。先程作成したtestphpimgを元にtestwebというコンテナを生成して、ローカルホスト宛の8080宛にアクセスすると、コンテナの80宛に転送されるようになっております。

もちろん、mhttp://localhost:8080/test.phpにアクセスしますと先程と同じ結果になると思います。

Dockerfileのコマンドたち

基本的な使い方を説明致しましたので、これより、様々なDockerfileのコマンドをご紹介してきたいと思います。なるべく実例も交えながらご説明していきます。

FROM

■ 書式

FROM [イメージ名]:[タグ名]

■ 解説と実例

FROMで指定したDockerイメージをベースに、これから記述するコマンドを実施しますよという意味です。以下の例ではCentOS7のイメージをベースに、様々なコマンドを実行するという意味になります。このFROMで指定したイメージをベースイメージと呼びます。

RUN

■ 書式

RUN [実行するコマンド]

■ 解説と実例

FROMで指定したイメージに対してコマンドを実行するためにはRUNを使います。以下の例では、ApacheとPHPをインストールします。

ちなみにもちろんですが、標準入力で何かを受け付けるようなコマンドは実施できません。なので、上記のyumでも「-y」オプションをつけています。「-y」オプションをつけないと、途中で本当にインストールしていいかどうかという確認を聞かれてしまいますので、そのようなことがないように「-y」オプションが必須です。

COPY

■ 書式

ADD [イメージ内にコピーしたいファイルのパス] [コピー先のイメージのパス]

■ 解説と実例

docker buildした結果できあがるDockerイメージ内にコピーしたいファイルを指定します。下記の例では、ホストPC上にあるhoge.txtをDockerイメージ上の/tmpディレクトリにコピーします。

ADD

■ 書式

ADD [イメージ内にコピーしたいファイルのパスやURLなど] [コピー先のイメージのパス]

■ 解説と実例

COPYコマンドとほぼ同じですが、以下の2点が異なります。

  • URLの指定が可能である
  • tarアーカイブでgzip、bzip2、xzで圧縮されていた場合、自動で展開される

例えば、hoge.txtをgzipで圧縮し、tarアーカイブしたhoge.tar.gzファイルは、イメージ上では展開されます。つまり、/tmp/hoge.txtという形でコピーされます。

 

そして、もう一つの例として、URLを指定してみます。以下の例だと、/tmpディレクトリにapache-tomcat-8.5.54.tar.gzが配置さてた状態でイメージが出来上がります(URLで指定したファイルがtar.gzであっても、展開は同時に行われないようです)。

CMD

■ 書式

CMD [コマンド]

■ 解説と実例

docker runコマンドで実行する際のコマンドを指定します。例えばdocker run時にfree -tコマンドを実行したい場合には以下のようなDockerfileを作成します。コマンド内のスペースは,(カンマ)で区切ります。

 

実行結果は以下の通りとなります。DockerfileでCMDコマンドで指定したfree -tが実行されているのがわかります。

 

Dockerfile内でCMDで指定したコマンドはdocker run時に上書きすることが可能です。CMDで定義したfree -tの代わりにls -laが実行されました。

ENTRYPOINT

■ 書式

ENTRYPOINT [コマンド]

■ 解説と実例

docker runコマンドで実行する際のコマンドを指定します。例えばdocker run時にfree -tコマンドを実行したい場合には以下のようなDockerfileを作成します。コマンド内のスペースは,(カンマ)で区切ります。

 

実行結果は以下の通りとなります。DockerfileでENTRYPOINYコマンドで指定したfree -tが実行されているのがわかります。

 

あれ、CMDと何が違うんだろうと思った方がいると思いますが、ENTRYPOINTでは、docker run時にENTRYPOINTで指定したコマンドの引数が追加できます。では、dockerrun時に-hオプションを追加してみます。-hオプションが追加されて、最終的にfree -t -hが実行されたのがわかります。

 

同様のことはDockerfile内でCMDを追加することでも実現できます。以下のようにDockerfileを記述します。

 

docker runコマンドを実行しますと、free -t -hを実行した結果が確認できます。

ENV

■ 書式

ENV [環境変数名]=[環境変数の値]

■ 解説と実例

docker buildでイメージを作成する際に指定する環境変数を定義することができます。利用用途としては、例えば、docker buildでビルドされるMySQLのコンテナを作成する際、そのDB接続ユーザー名やパスワードをビルドの結果作成されるイメージに埋め込みたい場合、このENVで環境変数としてDB接続ユーザー名やパスワードを渡します。

簡単な例で実践してみます。hogeという環境変数にfugaを定義してみます。以下のようなDockerfileを作成します。

 

実行結果は以下の通りとなります。RUN echo $hogeの結果がfugaと表示されているので、環境変数hogeが定義されているのがわかります。

 

EXPOSE

■ 書式

EXPOSE [ポート番号]

■ 解説と実例

Dockerコンテナ内で公開するポートを指定します。例えばApacheのコンテナを作成して80番ポートを公開するときは以下のようにDockerfileを作成します。

 

EXPOSEはDockerのコンテナのポートを公開するだけなので、もしホストPC(Dockerデーモンが起動しているPC)からDockerコンテナ内のApacheにアクセスする場合は、ホストPCのポートとコンテナのポートを紐付けてあげる必要があります。例えばホストPC上の8080ポートとコンテナの80ポートを紐付ける場合にはdocker runコマンドのオプションに-p 8080:80というのを指定する必要があります。早速実践してみましょう。

 

ブラウザからhttp://localhost:8080にアクセスすると、Apacheのデフォルトの画面が表示されます。

USER

■ 書式

USER [ユーザー名]

■ 解説と実例

DockerfileをもとにDockerイメージをビルドする際、その実行ユーザー名を指定できます。ntakeiというユーザーで/tmp/hoge.txtというファイルを作成して、そのファイルの所有者を見てみます。以下のDockerfileを作成します。

 

作成したファイルのユーザー名を確認してみます。/tmp/hoge.txtがntakeiというユーザー名で作成されていることがわかります。

まとめ

いかがでしたでしょうか?DockerfileはDockerを扱うときには欠かせないアイテムの一つです。Dockerfileをマスターして快適なDockerライフを過ごしましょう。No Dockerfile, No life!!

次回は以下になります。

【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その4:docker-composeってなに? 〜





ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!


ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

15人がこの投稿は役に立ったと言っています。

コメント投稿

メールアドレスは表示されません。


*