今更ながらdockerメモ
目次
- 目次
- サマリ
- 参考文献
- dockerのインストール
- dockerでhello world
- Docker Hubからdocker imageを取得して動かす
- オレオレdocker imageを作る
- Dockerのネットワーク機能
- Dockerにおけるデータ管理
サマリ
dockerをさわってみたのでメモ。
参考文献
ていねいなユーザマニュアルが標準装備なのはたいへんありがたいですね。
dockerのインストール
Ubuntuだとaptで入れられるのでらくちんですね。 なお、以下のバージョンしか公式にサポートしていない模様。 さらに、カーネルは3.10以上じゃないとダメ。
以下、手順。僕の環境はUbuntu 14.04。 ログアウトは、端末を開き直すだけじゃダメ。
sudo apt-get install linux-image-extra-$(uname -r)
は、
aufsを使うためだけっぽいのでいらないと思う。
# aptがhttpsを使えるように $ sudo aptitude update $ sudo aptitude install apt-transport-https ca-certificates # aptのGPG keyを追加 $ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D # /etc/apt/sources.list.d/docker.listをまっさらにして作りなおす $ echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list # aptのパッケージをアップデート $ sudo aptitude update # lxc-dockerをすでに入れていたらpurgeしておこう $ sudo aptitude purge lxc-docker # aptが正しくリポジトリを認識ているか確認しよう $ sudo apt-cache policy docker-engine # インストール! $ sudo apt-get install docker-engine # Dockerグループに自分をいれておくと、sudoしなくてもdockerコマンドをたたけるようになるので # いれておく $ sudo gpasswd -a $USER Docker # 一旦ログアウトしよう $ logout
dockerでhello world
docker run hello-world
して、以下のメッセージが出てきたら成功。
最初にDocker Hubからhello-worldイメージを取ってきて、
そこから起動するみたい。
$ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 03f4658f8b78: Pull complete a3ed95caeb02: Pull complete Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7 Status: Downloaded newer image for hello-world:latest Hello from Docker. This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker Hub account: https://hub.docker.com For more examples and ideas, visit: https://docs.docker.com/userguide/
Docker Hubからdocker imageを取得して動かす
GitHubみたいに、docker imageを置いておくことができる
Docker Hubというものがある。
公式リポジトリがいくつかあるようなので、そこから試しにubuntuを取得してみる。
docker pull <リポジトリ>:<タグ>
でdocker imageを取得できる。
<タグ>
を省略すると、最新版を取得する。
例えば、以下の例では、ubuntuリポジトリのタグ"14.04"を取得する。
$ docker pull ubuntu:14.04
取得したイメージはdocker images
で見られる。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 14.04 07c86167cdc4 2 days ago 188 MB hello-world latest 690ed74de00f 4 months ago 960 B
取得したものは、docker run
で動かすことができる。
取得しなくとも、docker run
を打つと、
勝手にDocker Hubに探しに行って取得してくれるので便利。
プログラムを動かしたままコンテナから脱出するにはCtrl-p
Ctrl-q
。
logoutしてしまうと、コンテナが停止してしまう。
# 単に動かす $ docker run ubuntu echo "hello world" ### ubuntuイメージがない場合はDocker Hubから勝手に取ってきてくれる hello world # backgroundで動かす $ docker run -d ubuntu echo "hello world" ### ubuntuイメージがない場合はDocker Hubから勝手に取ってきてくれる hello world # -itをつけると、対話型のプログラムも動かせる。 $ docker run -it ubuntu /bin/bash root@44d395e6298d:/# # コンテナに名前をつける $ docker run -it --name bash_test ubuntu /bin/bash
コンテナのリストを取得するのは、docker ps
docker ps -a
で、止まっているコンテナも見ることができる。
NAMES(コンテナの名前。以後コンテナ名とする)はDocker Engineが勝手につけてくれる(もちろん自分でつけてもよい)。 動かしたり止めたりするときに、コンテナIDを指定してもよいし、コンテナ名を指定してもよい。
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 44d395e6298d ubuntu:14.04 "/bin/bash" 13 seconds ago Exited (0) 3 seconds ago sharp_panini b4a331a7280d ubuntu:14.04 "echo 'hello world'" 26 seconds ago Exited (0) 25 seconds ago mad_hugle a627000187a6 hello-world "/hello" 8 minutes ago Exited (0) 8 minutes ago nostalgic_bhabha
お作法としては、コンテナは使い終わったら破棄。
停止しているコンテナの破棄は、docker rm
でできる。
# sharp_paniniを破棄 $ docker rm sharp_panini sharp_panini # いちいち指定するのが面倒なので全部破棄 $ docker rm $(docker ps -a -q) # --rmをつけてrunすると、終了後にdocker rm してくれる $ docker run --rm -it ubuntu /bin/bash
オレオレdocker imageを作る
直感的なやり方
いちばん直感的なのは、コンテナ起動して、必要なプログラムをインストールした後、コミットするやり方。 例えば、sysstatをインストール済みのコンテナを作るとすると、こんな感じになる。
$ docker run -it ubuntu:14.04 /bin/bash root@cd9379115537:/# sudo aptitude install sysstat root@cd9379115537:/# exit # -m はコミットログ。 -a は変更作成者。 # nbisco/sysstatというイメージを、testタグをつけて作成。 $ docker commit -m "Added sysstat" -a "nbisco" \ cd9379115537 nbisco/sysstat:test
Dockerfileを使うやり方
Dockerfileを使うと、いちいちコンテナ起動しなくても docker imageを作ることができる。
何はともあれ、まずはDockerfileを作る。
$ mkdir test $ cd test $ touch Dockerfile
Dockerfileを作ったら、以下を書き込む。 何のことはない、単にやってほしいことを書くだけだ。
# コメント行 FROM ubuntu:14.04 # どのイメージをベースにするか MAINTAINER nbisco <XXXX@XXXX.XXX> # イメージのメンテナはだれか RUN aptitude update && aptitude install -y sysstat # コンテナ起動後に実行するコマンド
Dockerfileを作ったら、以下のコマンドでイメージ作成。
# 最後の引数はDockerfileへのパスを指定すること。dotなので見落としがち。 $ docker build -t nbisco/sysstat:dev .
作ったimageは同じようにdocker run nbisco/sysstat:dev
で起動できる。
らくちん。
Dockerのネットワーク機能
コンテナにおけるネットワークは、(1)何とも繋がないnone、(2)ホストオンリーのhost、 (3)他コンテナやホストと繋げられるbridgeの3種類に大別できる。 デフォルトはbridge。
ネットワークは、以下のコマンドで確認できる。
$ docker network ls
NETWORK ID NAME DRIVER
18a2866682b8 none null
c288470c46f6 host host
7b369448dccb bridge bridge
ネットワークの状況は、docker network inspect <network名>
で調べられる。
※特に何も繋がっていない状況なので、"Containers"が空になっている。
$docker network inspect bridge [ { "Name": "bridge", "Id": "157fb4893818ff6e8fa7512b142b9e97df007f042d61f5bbc7bbdfbe9c9da2cb", "Scope": "local", "Driver": "bridge", "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16" } ] }, "Containers": {}, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" } } ]
動かしているコンテナのネットワークを切り離すこともできる。
$ docker run -d --name networktest training/webapp python app.py $ docker network disconnect bridge networktest
専用のbridgeネットワークを作って、コンテナ同士をつなげたりもできる。
# コンテナスタート時にネットワークを指定する場合 $ docker network create -d bridge my-bridge-network $ docker run -d --net=my-bridge-network --name network_test1 ubuntu $ docker run -it --net=my-bridge-network --name network_test2 ubuntu /bin/bash root@047745a86ac1:/# ping network_test1 PING db (172.18.0.3) 56(84) bytes of data. 64 bytes from db.my-bridge-network (172.18.0.3): icmp_seq=1 ttl=64 time=0.101 ms 64 bytes from db.my-bridge-network (172.18.0.3): icmp_seq=2 ttl=64 time=0.063 ms # 一旦止めれば、ネットワークに接続させることもできる $ docker run -it --name network_test3 ubuntu /bin/bash ★IPが172.18.0.0と別セグメントになっているので、届かない。 root@51057043d3ff:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02 inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:25 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:4814 (4.8 KB) TX bytes:648 (648.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) $ docker stop network_test3 $ docker network connect my-bridge-network network_test3 $ docker start network_test3 $ docker exec -it network_test3 /bin/bash root@51057043d3ff:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02 inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:26 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:4825 (4.8 KB) TX bytes:648 (648.0 B) # ★もう1個できて、network_test1/2とつながるようになった eth1 Link encap:Ethernet HWaddr 02:42:ac:12:00:04 inet addr:172.18.0.4 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe12:4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:26 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:4825 (4.8 KB) TX bytes:648 (648.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Dockerにおけるデータ管理
コンテナ起動時に-v
オプションをつけると、コンテナイメージに含まれない
ボリュームを作ることができる。例えばこんな感じ。
$ docker run -d -P -v /testweb --name web training/webapp python app.py $ docker exec -it web /bin/bash root@fc0beb95b345:/opt/webapp# ls / bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys testweb tmp usr var root@fc0beb95b345:/opt/webapp#
ボリュームの場所は、docker inspect
で調べられる。
ボリュームと言っても、単なるディレクトリに見えるので、作ったデータを取り出すのは簡単。
$ docker inspect web | less (略) "Mounts": [ { "Name": "08375e69b62c71792953d2dc83ac735c1c5cb8de63ac655557098f9446b95936", "Source": "/var/lib/docker/volumes/08375e69b62c71792953d2dc83ac735c1c5cb8de63ac655557098f9446b95936/_data", "Destination": "/testweb", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], (略) $ docker exec -it web /bin/bash docker exec -it web /bin/bash root@fc0beb95b345:/opt/webapp# touch /testweb/test.txt $ ls /var/lib/docker/volumes/08375e69b62c71792953d2dc83ac735c1c5cb8de63ac655557098f9446b95936/_data test.txt
既存のホストディレクトリをマウントすることもできる。 lsするとサブディレクトリ以下まで普通に見えてしまう。
$ mkdir /home/nbisco/test_docker $ touch /home/nbisco/test_docker/test.txt $ mkdir /home/nbisco/test_docker/test_docker_sub $ docker run -d -P -v /home/nbisco/test_docker:/test_docker --name web training/webapp python app.py $ docker exec -it web /bin/bash root@fce1df482e8d:/opt/webapp# ls /test_docker test_docker_sub test.txt
ディレクトリだけでなく、ファイルもマウントできちゃう。 わざわざdotfileをcloneしたりしなくて済むね。
$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash
もちろん、他のコンテナとディレクトリを共有することもできる。
Docker Userguideには、/dbdata
を共有する例が載ってる。
コンテナ間でディレクトリを共有すると、バックアップも手軽にできちゃう。
$ docker create -v /dbdata --name dbstore training/postgres /bin/true $ docker run -d --volumes-from dbstore --name db1 training/postgres $ docker run -d --volumes-from dbstore --name db2 training/postgres # バックアップの例 $ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata # バックアップから復元したデータでコンテナを動かす $ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
以上、ざっくり基本動作のメモでした。