docker buildコマンドの使い方とDockerfileからイメージを作成する一連の流れ

この記事では、Dockerfileを使って、Dockerイメージからコンテナを起動する手順について解説します。

具体的には、以下のようなことを学べます。

  • docker build -> docker runまでの流れ
  • Dockerfileの書き方・設定内容
  • Dockerfileを使ってイメージを作成する

簡単なサンプルは動かせたけど、少し複雑なことをしようとすると、手が止まってしまう。。という人に役に立てばうれしいです。

DockerまたはDocker toolboxがインストールされていることが前提ですので、まだの人は下の記事とかを参考に、Dockerをインストールしてください。

Docker Toolbox on Windowsのインストール手順と環境の構築Docker Toolbox on Windowsのインストール手順と環境の構築

簡単なDockerイメージをビルドしてみる

まず、全体像が分かった方が良いと思うので、さっそくDockerイメージをビルドしてみたいと思います。まず、適当なディレクトリを作成して、そこでビルドをしていきましょう。

例として、「c:\docker\sample001」で作業することにします。

ここに、「Dockerfile」という名前のファイルを作ります。名前はなんでもいいんですが、dockerコマンドは、デフォルトでこの名前を使うので。

中は以下のように記載します。

FROM ubuntu:latest

MAINTAINER pa-kun

RUN apt-get update && apt-get install -y apache2

EXPOSE 80

CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

Dockerfileが用意出来たら、Dockerのコマンドプロンプトで、作業ディレクトリ(c:\docker\sample001)に移動し、

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

を入力します。

Dockerfileの配置ディレクトリは、カレントディレクトリですので、例えば、

docker image build -t sample001:1.0 .

のように入力します。

ビルドを実行すると、ベースイメージのダウンロードや、RUNやCOPYの実行がステップごとに行われていることが分かります。

イメージができたかどうかはdocker image lsコマンドで確認できます。

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sample001           1.0                 f3ad3edd1505        45 hours ago        188MB

ここまで出来れば、Dockerイメージが出来上がっています。

では、docker runコマンドで、このイメージからコンテナを起動してみます。

docker run --name <起動するコンテナ名> -d <元にするイメージ名>

という構文になります。「-d」はバックグラウンドで動かすという意味です。

以下の例はdocker run --name con_sample001 -d sample001:1.0としました。

$ docker run --name con_sample001 -d sample001:1.0
cf2831d9c4aac720a5fcf2933ee1f28484eaf4af5e08e2b9a3ba241c01faf2dc

コンテナの起動に成功すると、「cf2831d9c4aac720a5fcf2933ee1f28484eaf4af5e08e2b9a3ba241c01faf2dc」といった文字列が表示されますが、これは、コンテナIDです。

無事起動できたかは、docker psコマンドで確認できます。これは、現在動いているコンテナを表示するコマンドです。

以下のように、コンテナが一つ、動いていることが分かります。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
cf2831d9c4aa        sample001:1.0       "/usr/sbin/apache2ct…"   6 seconds ago       Up 6 seconds        80/tcp              con_sample001

さて、ここまでで、Dockerfileからイメージの作成、コンテナの起動まで出来ました。

ひと通りの流れが分かったところで、Dockerfileの中身について、詳しく見てみることにしましょう。

なお、起動はしたけど、なぜかつながらない。。という人は、以下の記事を参考に、どこがおかしいかを探ってみてください。

Dockerコンテナで起動したサーバにアクセスできないときの確認と対処方法

Dockerfileの書き方・設定内容

dockerでは、Dockerfileにコマンドを書いていき、docker buildの引数として渡すことで、イメージをbuildしていきます。

DockerfileにはDoker独自のDSL(ドメイン固有言語)を使って、イメージの構成を定義していきます。

以下は、シンプルなDockerfileです。

FROMでリポジトリからイメージを取得し、RUNでイメージに対してモジュールのアップデートとapacheのインストールを行っています。

EXPOSEはdockerから外のネットワークに対してポートを開放し、最後にCMDを実行することで、コンテナをlive状態に維持しています。

FROMやRUNは「インストラクション(命令)」と呼ばれています。

様々なインストラクションが使えますが、まずは基本的なものを紹介します。

Dockerfileに記述できるインストラクション

詳しくは公式のDockerfileリファレンスを参照しても良いですが、以下で簡単に説明します。

FROM

FROMは、作成するDockerイメージのベースになるイメージを指定します。

Dockerfileでイメージをビルドする場合には、最初にFROMで指定されたイメージをダウンロードしてから実行されるため、最初の行に記述されます。

FROMで指定するイメージはDockerHubというレジストリで公開されています。Dockerはデフォルトの取得先として、このDockerHubのレジストリを参照します。

「FROM ubuntu:latest」のように、

FROM <イメージ名>:<タグ名>

または

FROM <イメージ名>

で指定します。

RUN

RUNは、Dockerイメージをビルドする際に、Dockerコンテナ内で実行するコマンドをそのまま記述できます。

上記の例のようにRUN apt-get update apt-get install -y apache2と記述すると、イメージが取得された後、コンテナ内で「apt-get update && apt-get install -y apache2」が実行されるということです。

COPY

COPYはDockerを動かしているホストPC上にあるファイルやディレクトリをDockerイメージ内にコピーします。

例えば、COPY html /var/www/html/のように記述すると、dockerホストから、イメージ内のファイルシステムにコピーします。

COPYと似たインストラクションにADDというのがあります。後ほど解説します。

ADD

ADDもCOPYと似たインストラクションで、ファイルやディレクトリをDockerイメージ内にコピー&配置します。

COPYとの違いは、ADDは、配置したときに、tarやgzなどの圧縮ファイルも解凍して配置してくれることと、dockerホスト上にないリモートのファイルも配置可能だということです。

つまり、ADD something.gz /tmpとしたら、/tmpに解凍して配置してくれます。

CMD

CMDインストラクションは、RUNと似ていて、コンテナ内で任意のコマンドを実行することができます。

CMD ["echo", "Dockerfile CMD demo"]のように記述すると、echoコマンドを実行することができます。

重要なのはその実行タイミング。

RUNは、イメージのビルド時に実行、コミットされますが、CMDはイメージからコンテナが実行されたときに一度だけ実行されます。また、実行できるのは1つのCMDだけで、Dockerfile中に何度記載しても、最後の1つのCMD以外は無視されます。

RUNでアプリケーションの更新や配置を行い、CMDでアプリケーションそのものを実行させると考えるとわかりやすいと思います。

ENTRYPOINT

ENTRYPOINTインストラクションもCMDと同様、コンテナ実行時に一回だけ実行されます。

ENTRYPOINT ["echo", "Dockerfile ENTRYPOINT demo"]のように記述することができます。

CMDとの主な違いは、CMDが、docker runの引数で実行コマンドを上書きできるのに対して、ENTRYPOINTは上書きされません。

そのため、ENTRYPOINTの方は、起動後も動き続けるタイプのコンテナに利用されることが多いです。