dotCloud製Linux Container, Docker触ってみた
とりあえず、VM一個立てて、rackupしようと思った。
digitaloceanのvpsで試していたんだけど、なんかおかしいと思ったらkernelのバグの影響だったようで、3.5.0-21以上を使ったほうが良さそう。 https://github.com/dotcloud/docker/issues/25
ちなみにdigitaloceanのvpsでは
$ uname -r 3.5.0-17-generic
なので、Vagrantで適当なUbuntuのVM立てた。
def v10(config) config.vm.box = "ubuntu-quantal" config.vm.box_url = "http://cloud-images.ubuntu.com/quantal/current/quantal-server-cloudimg-vagrant-amd64-disk1.box" end Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config| v10(config) end Vagrant::VERSION >= "1.1.0" and Vagrant.configure("1") do |config| v10(config) end Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config| config.vm.provider :virtualbox do |vb| config.vm.box = "ubuntu-quantal" config.vm.box_url = "http://cloud-images.ubuntu.com/quantal/current/quantal-server-cloudimg-vagrant-amd64-disk1.box" end end
$ uname -r 3.5.0-26-generic
Install
$ sudo apt-get install lxc wget bsdtar curl $ sudo apt-get install linux-image-extra-`uname -r` $ wget http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz $ tar -xf docker-master.tgz
基本(READMEに書いてる)
僕は当初Containerとimageを混同していて、$ sudo ./docker pull IMAGE_NAME
でVMのようなものを作っているのかと思ってたが、そうではなくimageはコンテナのひな形、インスタンスに対するクラスのようなもの。また、runで新しくコンテナを作ってコマンドを実行しても、コマンドが終了すればコンテナは消える。
# イメージのダウンロード $ sudo ./docker pull IMAGE_NAME # コンテナ上でコマンドを実行 $ sudo ./docker run -i -t IMAGE_NAME COMMAND # shell立ち上げることで、普通にそのコンテナにログインして作業みたいなこともできる $ sudo ./docker run -i -t IMAGE_NAME /bin/bash # Container の IDに対して操作出来る $ (sudo ./docker -d || echo "Docker daemon already running") & $ CONTAINER=$(docker run -d base /bin/sh -c "while true; do echo Hello world; sleep 1; done") $ echo $CONTAINER 2fa7019f6fdf3e85c249fa2c2eef093c294fc8c0d5262377e9754f491a3dc2e1 $ docker logs $CONTAINER 2013/03/29 07:33:54 docker logs 2fa7019f6fdf3e85c249fa2c2eef093c294fc8c0d5262377e9754f491a3dc2e1 Hello world Hello world Hello world Hello world Hello world Hello world $ docker logs $JOB 2013/03/29 07:33:56 docker logs 2fa7019f6fdf3e85c249fa2c2eef093c294fc8c0d5262377e9754f491a3dc2e1 Hello world Hello world Hello world Hello world Hello world Hello world Hello world Hello world $ docker kill $JOB 2013/03/29 07:34:23 docker kill 2fa7019f6fdf3e85c249fa2c2eef093c294fc8c0d5262377e9754f491a3dc2e1 # runはコンテナを新しく起動してコマンドを実行するもので、 # 永続的なコンテナを作るものではないので、コマンドの実行が終わると # コンテナは消える。 # コマンドの実行によりコンテナに与えた変更はcommitすることにより # 新たなimageが作成できる。 $ sudo ./docker run -i -t base bash root@ea19df583e44:/# adduser toqoz Adding user `toqoz' ... Adding new group `toqoz' (1000) ... Adding new user `toqoz' (1000) with group `toqoz' ... Creating home directory `/home/toqoz' ... Copying files from `/etc/skel' ... Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully Changing the user information for toqoz Enter the new value, or press ENTER for the default Full Name : Room Number : Work Phone : Home Phone : Other []: Is the information correct? [Y/n] root@ea19df583e44:/# su toqoz bash: no job control in this shell $ exit exit root@ea19df583e44:/# exit exit $ sudo ./docker run -i -t base bash 2013/03/29 08:08:37 docker run -i -t base bash bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell root@b612c0b3d72d:/# su toqoz Unknown id: toqoz
自分用のbase imageを作成
$ sudo ./docker pull base $ CONTAINER=$(docker run -d base apt-get install -y curl) $ docker commit -m "Installed curl" $CONTAINER $USER/sample $ docker push $USER/sample $ docker images 2013/03/29 08:16:58 docker images REPOSITORY TAG ID CREATED PARENT vagrant/sample latest c287f15311bfbb0c2e664f5e29561d5f8e03567b7a9f640140106213bbc6fa9d 45 seconds ago base:latest base latest b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc 5 days ago 27cf784147099545 base ubuntu-12.10 b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc 5 days ago 27cf784147099545 base ubuntu-quantal b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc 5 days ago 27cf784147099545 base ubuntu-quantl b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc 5 days ago 27cf784147099545 # ps でコンテナを探してattachすることもできる $ sudo ./docker ps 2013/03/29 09:12:28 docker ps ID IMAGE COMMAND CREATED STATUS COMMENT 307304dc7bd498f7ee3b8e76e3bbc492b8b1a7c698fb7e100c3b4d331e108d99 base:latest apt-get install -y r 5 minutes ago Up 5 minutes 61b385d5cd8ce70d3e6df7a256777aacdebf3cebb483285f50f006d6f0c17e00 base:latest echo hello 21 minutes ago Up 21 minutes 7ddd667b4edf3c603b89027a2f2f731b64c6b34487e2a03ab96daa4af3504cbe base:latest echo hoge 24 minutes ago Up 24 minutes $ sudo ./docker attach 307304dc7bd498f7ee3b8e76e3bbc492b8b1a7c698fb7e100c3b4d331e108d99
$ sudo ./docker commit -m 'dist-updated' $CONTAINER $USER/base # sudo ./docker run some_image apt-get update && apt-get install foo が # (sudo ./docker run some_image apt-get update) && apt-get install foo みたいな感じに解釈されてしまうので、とりあえず sh -c '' で実行してる $ CONTAINER=$(sudo ./docker run -d base sh -c '\ export DEBIAN_FRONTEND=noninteractive && \ echo "deb http://archive.ubuntu.com/ubuntu quantal-updates main universe multiverse" >> /etc/apt/sources.list && \ apt-get -y update && \ apt-get -y upgrade && \ apt-get -y dist-upgrade \ apt-get install -y build-essential openssl libreadline6 libreadline6-dev curl git-core' \ ) $ sudo ./docker commit -m 'Installed build-essential openssl libreadline6 libreadline6-dev curl git-core' $CONTAINER $USER/base
自分用のbase imageをベースにruby用のimageを作る
$ CONTAINER=$(sudo ./docker run -d $USER/base sh -c '\ export DEBIAN_FRONTEND=noninteractive && \ apt-get install -y libssl-dev zlib1g-dev libyaml-dev && \ cd /tmp && \ git clone git://github.com/sstephenson/ruby-build.git && \ cd ruby-build && PREFIX=/opt/ruby-build ./install.sh && \ /opt/ruby-build/bin/ruby-build --with-open-ssl-dir=usr 2.0.0-p0 /opt/ruby2.0.0' ) $ sudo ./docker commit -m 'Installed Ruby' $CONTAINER $USER/rubybase $ sudo ./docker run $USER/rubybase env PATH=/opt/ruby2.0.0/bin:$PATH ruby -v 2013/04/01 01:19:08 docker run vagrant/rubybase env PATH=/opt/ruby2.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games ruby -v ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
ruby用のimageをbaseにrack app用のimageを作る
$ CONTAINER=$(sudo ./docker run -d $USER/rubybase env PATH=/opt/ruby2.0.0/bin:$PATH gem install rack --no-ri --no-rdoc $ sudo ./docker commit -m 'Installed rack' $CONTAINER $USER/rackbase
rack appを起動するしてアクセスしてみる
$ CONTAINER=$(sudo ./docker run -d -p 9292 $USER/rackbase \ env PATH=/opt/ruby2.0.0/bin:$PATH \ sh -c 'rackup -b "run proc { |env| [200, { %{Content-Type} => %{text/html} }, %{Hello\n}.chars] }"' \ ) $ sudo ./docker logs $CONTAINER 2013/04/01 05:42:48 docker logs baa621dd4def [2013-04-01 05:42:38] INFO WEBrick 1.3.1 [2013-04-01 05:42:38] INFO ruby 2.0.0 (2013-02-24) [x86_64-linux] [2013-04-01 05:42:38] INFO WEBrick::HTTPServer#start: pid=5 port=9292 $ PORT=$(sudo ./docker port $CONTAINER 9292) $ HOST=$(ifconfig | grep 'inet ' | head -n1 | sed -e 's/^.*inet addr://' -e 's/ .*//') $ curl $HOST:$PORT Hello
実際にprivate paasみたいな感じで使うには
コンテナの存在をチェックして、再起動する仕組みと、ルーターを作れば、とりあえず簡素なの作れる気がした。
環境構築の自動化について
imageをpushすることも出来るので、chefなどを使った自動化というより、dockerのエコシステムの中でうまく自動化していくのがいいんじゃないかなと思ったりした。ただ現状、そのimageがどのように作られたかとかを知る術を僕は知りません。