実際に使うDocker超入門 (第1回)

こんにちはtatsyです。

今流行りのDockerですが、私も最近自分のプログラム・ビルド/テスト環境にDockerを導入して、実行時間の削減ができたりして、結構つかえるなぁと思い始めているところです。

今回の記事では、ハイパーバイザ型仮想化とかコンテナ型仮想化とかいう難しい話置いといて(できないだけ)、とりあえずDockerを使ってみましょう。

今回は記事が長くなりそうなので2つに分けます。第1回はDockerの簡単な使い方とDockerfileの簡単な書き方を説明しようと思います。

Dockerのインストール


私の実行環境はUbuntu 14.10 Utopicです。LTSでないのは許してください。

とにもかくにもapt-getを使ってインストールです。

$ sudo apt-get install docker.io

おそらくパッケージにはdocker(これは今使いたいDockerとは全くの別物らしい)とdocker.ioがありますが、Debian系の場合はdocker.ioです。

CentOSだとdocker-ioという名前みたいですね。

なお、Ubuntu 14.10の場合にはデフォルトのバージョンは1.2です。docker execが使えないなどの問題がありますので、バージョンを上げる方法も紹介しておきます。

バージョンを上げるためにはPPA(Private Package Archive)を使います。

$ sudo apt-add-repository ppa:docker-maint/testing
$ sudo apt-get update
$ sudo apt-get install docker.io

このコマンドを使うとバージョン1.7のDockerが入ります。

Dockerのユーザ設定


今の時点でDockerのインストールは出来ているのですが、この状態でdocker infoなどのDocker関係のコマンドを実行しようとすると、実行権限がないといって怒られます。

エラーメッセージに書いてある通りに/etc/groupdockerグループにDockerを使いたいユーザを追加してあげます。

直接groupを編集するのはどうなのかな、という気がしなくもないですが、その都度sudoをするのも面倒なので、今回は一番簡単な方法でいきます。

もしJenkinsなどからDockerを起動する場合にはjenkinsをユーザ登録しておけばよいと思います。

コンテナの起動


インストールができたら、Dockerのイメージからコンテナを起動します。

僕のような初心者のために補足しておくとイメージというのは、いわゆるOSのインストール・ディスクみたいなもので、コンテナは実際にそのOSをインストールしたマシンみたいなものです。

なお、初期状態ではイメージがありません。イメージを確認する方法は、

$ docker images

です。おそらく次のような出力がでると思いますが、いわゆるLinuxのOS名のようなものは確認できません。

$ docker images
REPOSITORY          TAG                   IMAGE ID            CREATED             VIRTUAL SIZE

そこで、Docker HubというDockerイメージのGitみたいなものからイメージを落としてきて、それを起動します。

今回はUbuntu 14.04 LTSのイメージを落とします。

$ docker pull ubuntu:14.04

しばらく待つとダウンロードが終わりますので、再度docker imagesを実行すると、

$ docker images
REPOSITORY          TAG                   IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04                 xxxxxxxxxxxx        6 weeks ago         188.4 MB

というような出力が得られると思います。IMAGE IDの部分は人それぞれだと思います。

実際にこのイメージを起動するにはdocker runコマンドを使います。起動して、そのコンテナのシェルに入るには

$ docker run -i -t ubuntu:14.04

というようなコマンドを実行します。オプションの-iはinteractiveの意味で、コンテナのシェルとinteractiveにコマンドをやり取りすると言う意味です(当たり前か)。

加えて-tというのは実行するイメージの名前を指定するものです。

あとは煮るなり焼くなり好きにコマンドが実行できます。

ちなみに、ログインをせずに単一のコマンドだけを実行する方法もあって、その場合には次のようにイメージ名指定のあとで実行したいコマンドを入れます。

$ docker run -t ubuntu:14.04 cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"

はい、いい感じです。これでイメージからコンテナを起動してコマンドを実行するところまではできました。

ちなみに、今回はわざわざpullをしてrunするという手順を踏んでいますが、Dockerが公式で配布しているものについては、pullをしないで直接runすると勝手にイメージを落としてきてくれます。

Dockerfileを使う


ここまでで、まっさらなUbuntuやCentOSを起動することはできるのですが、やはり自分なりのビルド環境なりテスト環境なりをイメージとして保存したくなります。

それを叶えてくれるのがDockerfileと呼ばれるスクリプトファイルです。読んで字のごとく(?)DockerfileとはMakefileをもじったもので新しいイメージをビルドするために使うものです。

内容はあとで解説しますが、例えば次のようなDockerfileを用意したとします(本家からのコピーです)。

#
# Ubuntu Dockerfile
#
# https://github.com/dockerfile/ubuntu
#

# Pull base image.
FROM ubuntu:14.04

# Install.
RUN \
  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get -y upgrade && \
  apt-get install -y build-essential && \
  apt-get install -y software-properties-common && \
  apt-get install -y byobu curl git htop man unzip vim wget && \
  rm -rf /var/lib/apt/lists/*

# Add files.
ADD root/.bashrc /root/.bashrc
ADD root/.gitconfig /root/.gitconfig
ADD root/.scripts /root/.scripts

# Set environment variables.
ENV HOME /root

# Define working directory.
WORKDIR /root

# Define default command.
CMD ["bash"]

手っ取り早くやるにはgit cloneしましょう。

$ git clone https://github.com/dockerfile/ubuntu.git

そうしたら、このDockerfileをビルドします。コマンドはdocker buildです。

$ cd ubuntu
$ docker build .

これで一応ビルドできるのですが、この状態でdocker imagesをしてみると、次のようになってしまいます。

REPOSITORY          TAG                   IMAGE ID            CREATED              VIRTUAL SIZE
<none>              <none>                xxxxxxxxxxxx        About a minute ago   490.9 MB

何が問題化というと、名前がになっていることです。これだと名前がないので起動するに不便です。

なので、実際にはタグを指定してビルドします。例えば次のような感じです。

$ docker build --tag=my-ubuntu .

そうするとdocker imagesの結果が次のように変わります。

$ docker images
REPOSITORY          TAG                   IMAGE ID            CREATED             VIRTUAL SIZE
my-ubuntu           latest                xxxxxxxxxxxx        4 minutes ago       490.9 MB

確かにREPOSITORYのところにtagで指定した名前が入っています。ちなみに<repository name>:<tag name>のように指定するとTAGの部分にも指定したものが入ります。

これで名前がついたので、コンテナを起動してみます。

$ docker run -i -t my-ubuntu

おそらく、これでシェルにログインできるはずです。

Dockerfileを書く


では、先ほどつかったDockerfileを使いながらDockerfileの書き方について説明していきます。

細かな仕様は公式のドキュメントを見ていただくとして、ポイントだけを解説します。

FROM

上記のDockerfileの最初に書いてある、

FROM ubuntu:14.04

という部分ですが、これはイメージをビルドする際に、起点となる既存のビルド済みイメージを指定するためのコマンドです。

上の場合ですと、ubuntu:14.04というベース・イメージを起点としています。ちなみに何も起点にしない場合はscratchを指定します。

RUN

その下にapt-get等の処理をしている行が何行かありますが、その最初にRUNというコマンドが使われています。

これは説明するまでもないかもしれませんが、普通のシェル上でのコマンドを実行する処理です。

一応気をつける点としては、複数行のコマンドを書く場合には、その都度RUNと書くか、あるいは行の末尾に&& \を付ける必要があるということです。

ENV

Dockerは一行ごとに実行して、その実行結果のイメージを作るので例えばexportなどをして環境変数を指定しても、次の行を実行する時にはその指定が無効になってしまいます。

もし環境変数を指定したい場合はENVコマンドを使います。

その他の注意

その他といいつつ以外と重要だったりするのはDockerfile内ではcdができないということです。

先ほど申し上げたとおりDockerfileのビルドは一行ごとに実行結果のイメージを作りますが、カレントディレクトリの情報などは保存されていないので、cdしても無意味なのです。

ではどうするかというと、cdを含む一連のコマンドは複数行コマンドとしてRUN一個で実行することです。よくありそうなシチュエーションとしてはCMakeを使ったビルドなどですね。

RUN \
  git clone https://github.com/xxxx/yyyy.git && \
  cd yyyy && \
  mkdir build && \
  cd build && \
  cmake .. && \
  cd -

みたいな感じです。

まとめ


このあたりで一旦まとめます。

  • Dockerのインストールはdocker.io (Debian系) あるいはdocker-io (CentOS)
  • 既存のイメージはdocker pullで取ってくる
  • コンテナの起動はdocker runを使う
  • Dockerfileは最低限、FROM、RUN、ENVがあれば多分大丈夫!

というかんじですかね。

第2回はC++のビルド環境をDockerfileで作って、それを自分のDocker Hubにデプロイ、そしてビルドに実際に使ってみるというところをやって見たいと思います。

実際に使うDocker超入門 (第2回)

それでは、今回も最後までお読み頂きありがとうございました。