Dockerfileとは?実際にビルドしながらイメージを作成してみよう!

Dockerfileとは?ビルドしながらイメージを作成

Dockerイメージを作成する方法は2つあります。

  1. 「docker build」コマンドで「Dockerfile」からイメージを作成
  2. 「docker commit」コマンドで「コンテナ」からイメージを作成

今回は、1つ目の「Dockerfile」と「docker build」コマンドを使ったイメージ作成の手順を紹介していきます。

「docker commit」によるコンテナのイメージ化に比べ、Dockerfileを使ったイメージ作成のほうがメリットも多いので、こちらもあわせて覚えておきましょう。

「docker commit」を使ったイメージ作成については、「Dockerコマンドでイメージ作成やコンテナ起動までの流れをつかもう!」で紹介していますので、気になる方は読んでみてください。

Dockerfileとは

Dockerfileとは、ベースイメージに加える変更をコードとして記述したファイルです。

このDockerfileを使うことで、簡単にオリジナルのDockerイメージを作成することができます。

ちなみに、ベースイメージに加えた変更は、その数だけ新たなイメージを作り、重なっていく仕組みになっています。

このイメージ1つ1つのことを「レイヤ」と呼び、Dockerイメージはこの「レイヤ(変更イメージ)」を重ねて新たなイメージを作っています。

そして、Dockerfileはこの「レイヤ」をコード化するための方法になります。

キツネ

Gitでいえば「リビジョン(コミットログ)」が「レイヤ」に似てるかも!

Dockerfileのメリット

Dockerfileを使わずに、コンテナに変更を加えたあとに「docker commit」を使ってイメージ化することもできます。

ですが、Dockerfileを使ったイメージ作成には、多くのメリットがあるのです。

  • 構築手順をコードとしてファイルに残せる
  • 構築手順の修正が簡単
  • 簡単に共有できる(ただのテキストファイルなので軽い)
  • バージョン管理ができる

Dockerfileを使わずにDockerイメージを共有した場合、ベースイメージにどのような変更を加えたのかがわからず、修正も困難です。

また、Dockerイメージを共有する際もテキストファイルのほうが軽くて速いですし、Gitでバージョン管理することもできます。

このように、インフラの構築をコード化して管理する考え方を「Infrastructure as Code」といいます。

キツネ

インフラ構築手順をコードに残すメリットは大きいね!

Dockerfileの作成

では、さっそくDockerfileを作成してみましょう。

ここでは、以下のようにCentOS7のイメージにレイヤを重ねる手順をDockerfileに記述します。

  1. CentOS7のベースイメージを取得
  2. CentOS7にNginxをインストール
  3. Nginxを起動(フォアグラウンド)

ここで注意しなければならないのが、最後の「フォアグラウンド」で起動させるところです。

サーバなどは通常バックグラウンドで起動させることが多いと思いますが、コンテナの場合、バックグラウンドでの実行は処理が終了したとみなされ、コンテナが停止するようになっています。

そのため、コンテナを利用する場合はフォアグラウンドで起動させ、処理が止まらないようにする必要があります。

Dockerfileの確認

では、Dockerfileの記述を確認してみましょう。

Dockerfileにコメントをつけているので、各命令コマンドが何をしているのか、なんとなくは理解できると思います。

詳しい命令コマンドの説明は、のちほど紹介します。

Dockerfile
# CentOS7のベースイメージを取得
FROM centos:7

# Nginxのインストール
RUN yum localinstall -y http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
RUN yum install -y nginx

# Nginxを起動(フォアグラウンドで動かす)
CMD ["nginx", "-g", "daemon off;"]

Dockerfileの作成に便利なコマンド

少し話は変わりますが、Dockerfileを作成するときに便利なコマンドも紹介しておきます。

これは、コンテナの起動と同時にログインし、ログアウトと同時にコンテナを削除するコマンドです。

Dockerfileを作成するときは、コンテナに対して変更を加えて、状態を確認しながらDockerfileに記述していくことが多いです。

以下のコマンドを使えば、まっさらなコンテナの状態にリセットしやすくなります。

Dockerfileを作成するときの便利コマンド
# コンテナを起動してログイン(「--rm」でコンテナ停止と同時に削除)
$ docker run -it -p 8080:80 --rm --name container-name image-name sh

Dockerfileの命令コマンド

Dockerfileの命令コマンドの種類についても、簡単にですが紹介しておきます。

ここで紹介するコマンドは一部なので、必要になったタイミングでほかのコマンドも調べてみてください。

FROM

「FROM」は、ベースイメージを指定します。

ここで指定されたイメージが「Docker Hub」にあるかを検索し、存在すれば自動でダウンロードするようになっています。

RUN

「RUN」は、ビルド時にコンテナ内で実行されるコマンドを記述します。

「yum」や「apt」などのコマンドを実行する際は、この「RUN」をメインに使います。

CMD

「CMD」は、イメージからコンテナを作成するときに実行するコマンドを記述します。

なので、基本的には1度しか実行されません。

COPY

「COPY」は、ホストマシンにあるファイルやディレクトリを、コンテナにコピーします。

NginxやApacheなどの設定ファイルをコピーする際に利用します。

ADD

「ADD」は、ホストマシンにあるファイルやディレクトリを、コンテナにコピーし展開(解凍)します。

ホストマシンにある圧縮ファイルの「コピー」と「展開」を同時におこないたい場合に便利です。

ENV

「ENV」は、Dockerfileの中で利用する環境変数を設定するための命令コマンドです。

CPで指定するファイルパスなど、何度も繰り返し出てくるような場合は設定しておきましょう。

WORKDIR

「WORKDIR」は、RUNやADDなどの命令コマンドを実行するディレクトリを設定します。

ディレクトリがない場合は自動で作成してくれるため、ディレクトリ作成と移動を同時にしたい場合にも使います。

特定のディレクトリで命令コマンドを実行することが多い場合は、設定するようにしましょう。

キツネ

他にもたくさんあるけど、必要になったときに調べればいいよ!

Dockerfileからイメージ作成(ビルド)

Dockerfileからイメージを作成するために「ビルド(build)」という作業をおこないます。

ビルドは「docker build」コマンドを使うことで簡単に実行できます。

以下では「docker build -t イメージ名 Dockerfileのパス」のように指定して実行しています。

ちなみに「-t」は、イメージ名を指定するためのオプションです。

Dockerイメージを作成(ビルド)
# Dockerfileからイメージを作成(ビルド)
$ docker build -t nginx:1 . 
Sending build context to Docker daemon  301.3MB
Step 1/4 : FROM centos:7
 ---> 9f38484d220f
Step 2/4 : RUN yum localinstall -y http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
 ---> Running in 82ac36081a66
   :
   :
Step 3/4 : RUN yum install -y nginx
 ---> Running in 6593271f60f7
   :
   :
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
 ---> Running in 6e374f874355
   :
   :

上のログを見てもらえるとわかりますが、Dockerfileに記述したレイヤがそれぞれ実行されているのがわかりますね。

Dockerイメージを作成したあとは、Dockerコンテナを作成し、起動するだけです。

Dockerコンテナを起動
# Dockerイメージを確認
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1                   3e281365b4e0        51 seconds ago      336MB

# Dockerコンテナを起動
$ docker run -it -d -p 8080:80 --name build-nginx nginx:1
b08178fdbe5eab350f9926fef2d469c462da8ccb0de561269c6b0383400b520b

# 起動中のDockerコンテナを確認
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b08178fdbe5e        nginx:1             "nginx -g 'daemon of…"   8 seconds ago       Up 7 seconds        0.0.0.0:8080->80/tcp   build-nginx

コンテナが起動したら、ブラウザからNginxへアクセスしてみましょう。

「http://IPアドレス:8080」でアクセスできるはずです。

Dockerビルド(docker build)時はキャッシュされる

Dockerビルドをした際に、レイヤが「キャッシュ」されるという特徴があります。

たとえば、さきほどと同じDockerfileから別のイメージを作るためにビルドをすると、以下のように「Using cache」と表示されます。さきほどの実行ログにはなかったワードです。

Dockerビルド
$ docker build -t nginx:2 .
Sending build context to Docker daemon  301.3MB
Step 1/4 : FROM centos:7
 ---> 9f38484d220f
Step 2/4 : RUN yum localinstall -y http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
 ---> Using cache
 ---> a33798ba0561
Step 3/4 : RUN yum install -y nginx
 ---> Using cache
 ---> 5a2305061706
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
 ---> Using cache

さきほどビルドしたDockerイメージのレイヤをキャッシュしているため、実行時間や実行ログが短縮されているのがわかります。

ただし、Dockerfileに新たな命令コマンドを追加すると、その追加した行から下の命令はキャッシュされません。

ビルド時間を短縮するためにも、変更が少ないコマンドはDockerfileの上のほうに、変更頻度が高そうなコマンドは下のほうに書くようにしましょう。

イメージのレイヤを増やし過ぎない

Dockerfileの命令コマンドの数だけ、Dockerイメージのレイヤが増えていきます。

そして、このレイヤが増えていくと、Dockerイメージのサイズもどんどん大きくなっていきます。

できるだけDockerイメージを軽くしておくためにも、「まとめられるコマンドはまとめておく」といいです。

たとえば

「RUN yum install -y hoge」

「RUN yum install -y fuga」

と分けずに

「RUN yum install -y hoge fuga」

と、1つにまとめてしまったほうがいいってことです。

ただし、頻繁に変更が発生しそうなコマンドは、あえてまとめずに分けておくことも大切です。

これは、さきほど紹介した「イメージのキャッシュ」を利用したいからです。

キツネ

ここらへんのバランスは実際に書きながら覚えていこう!

まとめ

Dockerfileに命令コマンドを記述し、「docker build」コマンドを実行することで、簡単にDockerイメージをビルドできました。

Dockerイメージの作成は、開発環境を構築するエンジニアであれば、必ずできるようになっておきたいですね。

次は「【Dockerネットワーク】コンテナ間の通信に挑戦する【RailsとMysql】」を読んで、コンテナ同士を連携させる「Dockerネットワーク」について学んでみましょう。

テキストのコピーはできません。