Dockerイメージを作成する方法は2つあります。
- 「docker build」コマンドで「Dockerfile」からイメージを作成
- 「docker commit」コマンドで「コンテナ」からイメージを作成
今回は、1つ目の「Dockerfile」と「docker build」コマンドを使ったイメージ作成の手順を紹介していきます。
「docker commit」によるコンテナのイメージ化に比べ、Dockerfileを使ったイメージ作成のほうがメリットも多いため、こちらを覚えておきましょう。
「docker commit」を使ったイメージ作成については、こちらの記事で詳しく紹介していますので、気になる方は読んでみてください。

もくじ
Dockerfileとは
Dockerfileとは、ベースイメージに加える変更をコードとして記述したファイルです。
このDockerfileを使うことで、簡単にオリジナルのDockerイメージを作成することができます。
ちなみに、ベースイメージに加えた変更は、その数だけ新たなイメージを作り、重なっていく仕組みになっています。
このイメージ1つ1つのことを「レイヤ」と呼び、Dockerイメージはこのレイヤ(変更イメージ)を重ねて、新たなイメージを作っていきます。
そして、Dockerfileはこの「レイヤ」をコード化するための方法になります。
Dockerfileのメリット
Dockerfileを使わず、コンテナに変更を加えたあとに「docker commit」を使ってイメージ化することもできます。
ですが、Dockerfileを使ったイメージ作成には、多くのメリットがあるのです。
- 構築手順をコードとしてファイルに残せる
- 構築手順の修正が簡単
- 簡単に共有できる(ただのテキストファイルなので軽い)
- バージョン管理ができる
Dockerfileを使わずにDockerイメージを共有した場合、ベースイメージにどのような変更を加えたのかがわからず、修正も困難です。
それに比べ、Dockerfileであれば変更点が可視化されるだけでなく、Dockerイメージを共有する際もテキストファイルなので軽くて速いですし、Gitでバージョン管理することもできるのです。
このように、インフラの構築をコード化して管理する考え方を「Infrastructure as Code」といいます。
Dockerfileの作成
では、さっそくDockerfileを作成してみましょう。
ここでは以下のように、CentOS7のイメージにレイヤを重ねる手順をDockerfileに記述します。
- CentOS7のベースイメージを取得
- CentOS7にNginxをインストール
- Nginxを起動(フォアグラウンド)
ここで注意しなければならないのが、最後の「フォアグラウンド」で起動させるところです。
サーバなどは通常バックグラウンドで起動させることが多いと思いますが、コンテナの場合、バックグラウンドでの実行は処理が終了したとみなされ、コンテナが停止するようになっています。
そのため、コンテナを利用する場合はフォアグラウンドで起動させ、処理が止まらないようにする必要があります。
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に記述していくことが多いです。
以下のコマンドを使えば、まっさらなコンテナの状態にリセットしやすくなります。
# コンテナを起動してログイン(「--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からイメージ作成(build)
Dockerfileからイメージを作成するために「ビルド(build)」という作業をおこないます。
ビルドは「docker build」コマンドを使うことで簡単に実行できます。
以下では「docker build -t イメージ名 Dockerfileのパス」のように指定して実行しています。
ちなみに「-t」は、イメージ名を指定するためのオプションです。
# 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 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 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の上のほうに、変更頻度が高そうなコマンドは下のほうに書くようにしましょう。
Dockerイメージのレイヤを増やし過ぎない
Dockerfileの命令コマンドの数だけ、Dockerイメージのレイヤが増えていきます。
そして、このレイヤが増えていくと、Dockerイメージのサイズもどんどん大きくなっていきます。
できるだけDockerイメージを軽くしておくためにも、「まとめられるコマンドはまとめておく」といいです。
たとえば
「RUN yum install -y hoge」
「RUN yum install -y fuga」
と分けずに
「RUN yum install -y hoge fuga」
と、1つにまとめてしまったほうがいいってことです。
ただし、頻繁に変更が発生しそうなコマンドは、あえてまとめずに分けておくことも大切です。
これは、さきほど紹介した「イメージのキャッシュ」を利用したいからです。
まとめ:Dockerネットワークにも挑戦しよう!
Dockerfileに命令コマンドを記述し、「docker build」コマンドを実行することで、簡単にDockerイメージをビルドできました。
Dockerイメージの作成は、開発環境を構築するエンジニアであれば、必ずできるようになっておきたいところですね。
次は「Dockerネットワークでコンテナ間通信」を読んで、コンテナ同士を連携させる「Dockerネットワーク」について学んでみましょう。
またね、キツネ(@kitaaaa_kitsune)でした!

