実例で学ぶDockerfileの具体的な作成手順

インフラ

こんにちは。仁科(@nishina555)です。

Dockerはコンテナ型の仮想環境を提供するもので、Dockerにより同じ開発環境を簡単に複数の人で共有することが可能になります。
Dockerfileはその環境を構築するためのファイルで、このファイルさえあれば同じ環境を手に入れることができます。

Dockerを使うことで共同開発する人が同じ開発環境を利用できたり、ローカル環境にわざわざインストールしなくてもミドルウェアが使えたりできるといったメリットがあります。
ですので、Dockerfileを作ってみんなに共有したいというケースが出てくることもあると思いますが、実際にゼロからDockerfileを作ろうと思うとどうやって作ればいいかわかりにくいと思います。

今回、erdというER図をテキストベースで作成できるツールをローカルにインストールした際に導入が面倒だったのでDocker化したので、その時の手順を具体的に記述し、どのようにDockerfileを作成していくか説明をします。

Dockerのおさらい

まず具体的な話をする前に簡単にDockerの用語について確認をしていきます。

Dockerコンテナ

自分のPC上に存在する仮想的環境のことを指します。
いわゆる、VMwareとかVirtualBoxとかで作る仮想環境などの仲間だと考えてもらっていいです(VMwareとかVirtualBoxとかの仮想環境はハイパーバイザ型などと言われます)。
コンテナ型の仮想環境はハイパーバイザ型と違い、軽量である、環境の破棄・再作成が高速である、などのメリットがあります。
また、Dockerイメージからコンテナは作成されます。

Dockerイメージ

コンテナを作成するためのファイルシステムや設定をまとめたもののことをいいます。
Docker Hubからイメージをダウンロードしてきたり、DockerファイルからビルドしたりすることでDockerイメージを作成することができます。

Dockerfile

Dockerイメージを作成するための手順が書かれているファイルのことです。
Dockerfileを共有することで違うPCでも同じ環境を利用することができます。
今回の例では、erdというツールを利用できる環境構築の手順をDockerfileに記述していくことになります。

今回の例について

ER図をテキストベースで作成できるerdというツールが利用できる環境をDockerfileに落とし込んでいきます。
まずは、erdというものとDockerfileの完成形について説明します。

erdについて

本家はこちらになります。
例えば、stack exec ere -- -i examples/test.er -o test.pngというコマンドを打つことで指定されたフォーマットで記述したtest.erからtest.pngという画像ファイルを作成することができます。
ただし、本家に

erd requires Haskell and GraphViz

と書かれているようにerdを利用するためには他にもインストールをする必要があります。

Dockerファイルの完成形

今回は以下のようなDockerファイルを作成していきます。

FROM centos:7
RUN yum -y install wget
RUN yum -y install git
RUN yum -y install 'graphviz*'
RUN wget -qO- https://get.haskellstack.org/ | sh
RUN git clone https://github.com/BurntSushi/erd.git
RUN cd /erd && \
stack init && \
stack setup && \
stack build

Dockerfileを作るサイクル

前置きが長くなりましたが、今回話をしたかったDockerfileの作り方の手順について説明をします。
結論としては、以下のようなサイクルでDockerfileを作成すると効率よく作成できると思います。

  1. コンテナにログインし、コマンド(yum installとかmakeとか)を実行する
  2. うまくいったコマンドをDockerファイル(もしくはメモなど)に記述する
  3. コンテナからログアウトし、作成したコンテナをコミットして新しいDockerイメージを作成する
  4. コンテナに再度ログインする(1に戻る)

以下では、このサイクルをベースについて具体的な内容の説明をします。

コンテナにログインし、コマンドを実行する

まずは、wgetgitをインストールしてみたいと思います。

コンテナへのログインは以下のように実行します。

# centos:7からerdというコンテナを作成し、ログイン
$ docker run -it --name erd centos:7 /bin/bash

上記のコマンドでコンテナにログインできたので、実際にコマンドが実行できるか確認できます。

[root@437ea34ff394 /]# yum -y install wget
...
...
Installed:
wget.x86_64 0:1.14-13.el7

Complete!
[root@437ea34ff394 /]# yum -y install git
...
...
Complete!

うまくいったコマンドをDockerファイルに記述する

先ほど、centosをベースにwgetgitをインストールすることができました。
ですので、Dockerfileに記述していきます。

FROM centos:7
RUN yum -y install wget
RUN yum -y install git

コンテナからログアウトし、作成したコンテナをコミットして新しいDockerイメージを作成する

まずはコンテナからログアウトします。ctrl + p + ctrl + qでログアウトできます。
その後、先ほど作成したコンテナ(gitwgetがインストールされたもの)をコミットします。コミットとはコンテナの状態をDockerのイメージとして保存することをいいます。
下の例ではerdというコンテナをcentos:init_settingというイメージでコミットしています。

$ docker commit erd centos:init_setting

コミットが完了したら、イメージが作成されていることが確認できます。
下がベースのイメージ、上が先ほど作成した(wgetgitがインストールされているcentos)イメージです。

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos init_setting 5c51ad3faf22 9 seconds ago 325 MB
centos 7 67591570dd29 3 months ago 192 MB

コンテナに再度ログインする

一番はじめの”1.コンテナにログインし、コマンドを実行する”に戻って作業を続けます。
もし、コマンドがうまくいき、継続してコンテナ上でコマンドを実行したいのであればdocker attachを利用します。
今回の場合であればdocker attach erderdコンテナに再度ログインしてインストール作業を続けます。

コマンドがうまくいかなかったりコンテナをやり直したければコンテナを破棄し、Dockerイメージからコンテナを再作成します。
このとき、途中でコミットされているイメージがあれば、途中から続けることができます。
例えば、今の例でいえば、

$ docker run -it --name erd centos:init_setting /bin/bash

を実行するとgitwgetが既にインストールされているcentosをベースに作業を継続することができます。

(参考) コミットした後の流れについて

git, wgetをした後、他のツールのインストールを検証したい場合の例を示します。

$ docker attach
[root@cc7612db9d79 /]# yum -y install 'graphviz*'
[root@cc7612db9d79 /]# wget -qO- https://get.haskellstack.org/ | sh
[root@cc7612db9d79 /]# git clone https://github.com/BurntSushi/erd.git
# ツールをインストールした状態をコミットする
$ docker commit erd centos:tool_install
# 新しくイメージが登録されているのがわかる。
$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
centos tool_install a9e16a7d58e7 7 seconds ago 579 MB
centos init_setting 5c51ad3faf22 16 minutes ago 325 MB
centos 7 67591570dd29 3 months ago 192 MB

Dockerfileに以下を追加します。

RUN yum -y install 'graphviz*'
RUN wget -qO- https://get.haskellstack.org/ | sh
RUN git clone https://github.com/BurntSushi/erd.git

Docker化したerdの使い方について

実際に作成したDocker化したerdについては以下の記事で詳細を記述しました。
erdについては細かいことは説明しないので、興味がある方は以下の記事もご覧になってみてください。

まとめ

今回はDockerfileを作成する手順について説明をしました。

繰り返しになりますが、以下のようなサイクルをまわすことでDockerfileを効率よく作成することができます。

  1. コンテナにログインし、コマンド(yum installとかmakeとか)を実行する
  2. うまくいったコマンドをDockerファイル(もしくはメモなど)に記述する
  3. コンテナからログアウトし、作成したコンテナをコミットして新しいDockerイメージを作成する
  4. コンテナに再度ログインする(1に戻る)

特に、ちゃんと実行できるかわからないコマンドの前や、実行にとても時間のかかる処理を行った後などはdocker commitをすることをおすすめします。
そして、Dockerイメージのビルドは時間がかかるため、Dockerfileが完成した後にビルドを実行するのがいいでしょう。

最後に

今回のDockerfileは本家をForkしたこちらに置いておきました。

参考

テキストベースでER図を書く
erdでテキストベースにER図を描く