2014年5月9日金曜日

Dockerを使ってみました。

Dockerを使って見ました。

ちょっとまえにもさわったことがあるのですが、最近流行りのDockerをつかってみました。Dockerとはコンテナタイプの仮想環境に独自の機能を組み合わせて使いやすく便利にしたもののようです。

 コンテナタイプ

kvmといったいわゆる仮想マシンのようにまるごと物理マシンをエミュレーションした環境を用意するのではく、ネットワークやプロセスIDなどのみが独立した環境(コンテナ)を用意してその中でプロセスを実行するタイプの仮想環境です。仮想マシンと比較すると圧倒的に軽い(ホストに対する負荷が低い)のが特徴みたいです。

最近またバージョンがあがってDockerの最新版は0.10のようです。

Dorkerに必要なもの

カーネル

Linuxでコンテナ機能を利用するためにはカーネルが以下の機能をサポートしている必要があります。
  • Namespace(名前空間)
  • Cgroups

Namespace

ネットワークやプロセスID、ユーザIDなどについてそれらが独立した環境を用意するカーネルの機能です。

Cgroups

プロセスにが利用できるリソース(CPUの数やメモリの量)を制限するカーネルの機能です。

 それぞれかなり前のバージョンから一部はサポートされていましたが、Dockerを使うためには必要なすべて機能がそろった3.8以降のカーネルが必要です。
  •   もちろん、カーネルコンフィグで機能が有効になっている必要があります。

以下の2つはちょっと前までは必要だったのですが、最新バージョンでは必要でなくなったものです。

Aufsファイルシステム

Dokerはコンテナのイメージ(ディレクトリツリー)を格納するのにaufsを利用していましたが、aufsは標準カーネルにマージされていないので、利用するためにはパッチをカーネルにあてる必要がありました。そのためDockerはディストリビューションの標準カーネルでは動かないケースがあり、パッケージとしても提供されていないディストリビューションもあったようです。
  • ubuntuなどはaufsパッチの当たっているカーネルを採用していて、パッケージとしてもDockerが提供されていました。
最近(といってもちょっと前ですが)aufsが必須ではなくなり、ディストリビューションに関係なく動作するようになりました。
  • ただaufsのパッチをカーネルに当てて、aufsとの組み合わせでdockerを利用している人はまだ多いみたいです。

lxc(linux container)

Dockerの以前のバージョンではコンテナを作成したりするのに、lxcと呼ばれる(Dockerとは別の)ツールを利用していました。最新のDockerではこの部分がDocker側に実装されてたのでこれも必須ではなくなりました。
  • lxcとの組み合わせで最新版のDockerを動作させることは可能です。

インストール

最近のディストリビューションではパッケージとしてDockerが提供されているところも多いようです。その場合は当然上記のカーネルに必要な機能などはすでに満たされているでしょうから、apt-getやyumといったパッケージ管理ツールでインストールすればOKです。

 今回は上記の必要なカーネルの機能やファイルシステムは揃っているとしてパッケージを使わずに直接Dockerをインストールしてみます。

バイナリインストール

詳しい説明は以下にかかれています。
  http://docs.docker.io/installation/binaries/
  •  まず、DockerのページからDockerのバイナリをダウンロードしてきます。
    • Docker本体として必要なものはこのバイナリだけです。
    • Dockerに必要な機能(デーモンやコマンドラインインターフェースなど)はすべてこのコマンド+オプションの組み合わせで実行します。
  •  そして、ダウンロードしてきたバイナリをパスの通っている場所に置けば完了!
# cp docker /usr/local/bin/
 staticなバイナリとなっているので実行するライブラリなども必要ないようです(なのでちょっとサイズは大きい)

 カーネルの条件させ満たしていれば、パッケージなどがなくてもDockerのインストールは簡単です。

その他インストールするもの

上記のページによると以下のものもインストールしないといけないようです。
  • iptables
  • git
  • psコマンド
  • xzユーティリティ
これらは既にインストールされているか、なくてもほとんどのディストリビューションでパッケージとして提供されているとおもいます。

使ってみる

 さっそくDockerをつかってみます。

Dockerディレクトリの準備

 /var/lib/dockerがデフォルトでDockerが利用する(イメージやその他を保存する)ディレクトリです。
  • Dockerデーモンの起動時のオプションで別の場所も指定することもできます。中身を特に準備する必要は有りません。ディレクトリだけつくっておきます。
  • 作らなくても初回デーモン実行時に作成されるようです。
    # mkdir /var/lib/docker
 ディストリビューションのパッケージでインストールした場合はインストールの過程ですでに作られていると思います。

cgroupfsのマウント

Dockerを利用するためにdockerデーモンを起動する必要がありますが、そのまえにcgroupfsのマウントが必要です。
  •  以前のちょっとさわったときのDockerのバージョンでは以下のように簡単にマウントするだけでOKだった(と思った)のですが、最新のものでは別の方法でマウントする必要があるようです。
    # mount -t cgroup cgroup /sys/fs/cgroup (これではダメ)
  • マウントするためのスクリプトがDockerのページからダウンロードできるのでこれを利用します。
    • https://raw.githubusercontent.com/tianon/cgroupfs-mount/master/cgroupfs-mount
# wget  https://raw.githubusercontent.com/tianon/cgroupfs-mount/master/cgroupfs-mount
# sh ./cgroup-mount
cgroupfsのマウント場所はどこでもいいのですが、/sys/fs/cgroup以下にするのが一般的なようです(スクリプトもそうなっています)

 ディストリビューションのDockerパッケージでインストールした場合、/etc/init.d/の下などに起動用のスクリプトが用意されると思います。それをいつもの方法で起動すれば、適切にcgroupfsのマウントなどを行った後、Dockerデーモンを起動してくれるとおもいます。

Dockerデーモンの起動

cgroupfsのマウントが終わったらdockerデーモン起動です。dockerデーモン起動はdockerコマンドを利用します。
  • しつこいようですが、Dockerはこのdockerコマンドしか使用しません。
# docker -d &
    • -d オプションでデーモンモードで起動します。この際にいくつかのオプション(今回は省略)を指定できます。-d オプションをつけてもバックグラウンドにはならないので、そうしたい場合"&"が必要です。

コンテナの中身の準備

これでDockerを実行する準備は整いました。まずコンテナの中身(イメージ)を準備しましょう。コンテナの中身として必要なものは簡単に言えばコンテナ内で実行したいアプリケーションとそれを実行するためのルートファイルシステムです。
  •   アプリケーションを実行するためには、ライブラリや他のコマンドが必要なのでルートファイルシステムをまとめて用意する感じなのだと思います。またapt-getなどのコマンドもあればコンテナ上でそれ実行してアプリケーションをインストールすることもできるでしょう。
コンテナの中身は1から自分で作成することももちろんできますが、Dockerのオフィシャルレポジトリに様々なコンテナのイメージが登録されているのでそれを利用することもできます(むしろそれを積極的に利用するのが流儀のようです)
  • レポジトリとからベースとなるイメージを取得してきて、それに自分に必要なアプリケーションをインストール(デプロイ)するのがよくあるやり方のようです。
  • アプリケーションまですでにインストールされている(あとは実行するだけの)コンテナのイメージも多数登録されています。
 とりあえず、今回はubuntuのベースイメージを取得してみましょう。
  •  コマンドは"docker pull イメージ名"で取得できます。
# docker pull ubuntu
Pulling repository ubuntu
3db9c44f4520: Download complete
99ec81b80c55: Download complete
5e019ab7bf6d: Download complete
a7cf8ae4e998: Download complete
316b678ddf48: Download complete
74fe38d11401: Download complete
511136ea3c5a: Download complete
02dae1c13f51: Download complete
e7206bfc66aa: Download complete
cb12405ee8fa: Download complete
f10ebce2c0e1: Download complete
ef519c9ee91a: Download complete
e2aa6665d371: Download complete
5e66087f3ffe: Download complete
6cfa4d1f33fb: Download complete
f0ee64c4df74: Download complete
82cdea7ab5b5: Download complete
2209cbf9dcd3: Download complete
5dbd9cb5a02f: Download complete
07302703becc: Download complete
cf8dc907452c: Download complete
4d26dd3ebc1c: Download complete
d4010efcfd86: Download complete
  • 今回はタグで細かく指定していないので、ubuntuという名前がつくものは全部取得されています。
  • docker pullを実行した際に下記のようなエラーが出る場合、ca-certificatesパッケージをインストールすれば大丈夫のようです。
    Get https://index.docker.io/v1/repositories/ubuntu/images: x509: failed to load system roots and no roots provided
# apt-get install ca-certificates
    • インストールしたあとはDockerデーモンの再起動が必要です。 

 取得したイメージはdocker imagesで確認できます。
  • イメージはレポジトリ名とタグで表現されていて、イメージIDが同一であれば同じ実体を示しています。
    • 下記の場合、タグがlatest,trusty,14.04のものは同じ実体です。
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              saucy               5e019ab7bf6d        12 days ago         180 MB
ubuntu              13.10               5e019ab7bf6d        12 days ago         180 MB
ubuntu              12.04               74fe38d11401        12 days ago         209.4 MB
ubuntu              precise             74fe38d11401        12 days ago         209.4 MB
ubuntu              quantal             a7cf8ae4e998        12 days ago         171.2 MB
ubuntu              12.10               a7cf8ae4e998        12 days ago         171.2 MB
ubuntu              latest              99ec81b80c55        12 days ago         266 MB
ubuntu              trusty              99ec81b80c55        12 days ago         266 MB
ubuntu              14.04               99ec81b80c55        12 days ago         266 MB
ubuntu              13.04               316b678ddf48        12 days ago         169.4 MB
ubuntu              raring              316b678ddf48        12 days ago         169.4 MB
ubuntu              10.04               3db9c44f4520        2 weeks ago         183 MB
ubuntu              lucid               3db9c44f4520        2 weeks ago         183 MB

コンテナの実行

コンテナの実行というよりは、コンテナ上でコマンドを実行するという意味です。
  • コンテナの存在意義のためには実行するコマンド(アプリケーション)が必要です。
  • 今回はとりあえず、コンテナ上でシェル(/bin/bash)を実行してみます。
  • コンテナの実行にはdocker runコマンドを利用します。
# docker run [オプション] <イメージ名>[:タグ名] [コマンド] [コマンドの引数] ...
  • イメージのタグを省略した場合、"latest"が指定されたものと解釈されます。
  • 下記の例ではubuntu:latest、すなわちubuntu version 14.04のイメージ上でシェルが実行されます。
    • -t オプションは(仮想)端末を開くオプション、-iは標準入力をキープするオプションです。シェルを実行して、入力を受け付けるために指定しています。
# docker run -t -i ubuntu /bin/bash
root@9be1af7efb11:/# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS"
  •  ubuntu 14.04の環境上でシェル(bash)が実行されているのがわかります。
実行しているコンテナはdocker psコマンドで確認できます。
  •  別の端末から
# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9be1af7efb11        ubuntu:latest       /bin/bash           5 seconds ago       Up 4 seconds                            stoic_blackwell  

コマンドの設定

今回は省略しますが、コンテナのイメージにはそのコンテナ上で実行するコマンド(アプリケーション)をあらかじめ設定することができます。
  •   特にコマンドを指定しないでコンテナを"実行"した場合にはそのコマンドが実行されます。
  • 先ほど、取得してきたコンテナはベースのイメージなので実行するコマンドは設定されていません。
  • コマンドを指定しないで実行するとエラーになります。

コンテナの停止

dockerのコンテナは実行時に指定したコマンドが終了するとコンテナも終了します。
  •  コマンドが終了するとコンテナの存在意義もなくなります。
上記のbashを実行した例では、bashから抜けると同時にコンテナも終了します。

root@9be1af7efb11:/# exit (上記で実行したシェルを抜ける)
# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES




まとめ

最新版になってパッケージが提供されていなくても、Dockerをインストールして実行するのはかなり簡単になったようです。カーネルのバージョンと機能の問題はありますが、最近のディストリビューションの最新のカーネルであればあまり問題はないとおもいます。