既然有了boot2docker,不妨下几个容器来玩玩。先看下本地的docker服务的信息。
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
docker@boot2docker:~$  docker info
 Containers: 0
 Images: 0
 Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Dirs: 0
 Execution Driver: native-0.2
 Kernel Version: 3.16.7-tinycore64
 Operating System: Boot2Docker 1.4.1 ( TCL 5.4) ;  master : 86f7ec8 - Tue Dec 16  23:11:29 UTC 2014
 CPUs: 4
 Total Memory: 1.961 GiB
 Name: boot2docker
 ID: L5JR:QYWN:KEDD:FQ4O:66IY:FUE6:OXTA:SWAE:UV2R:LFCF:7H6H:PTS5
 Debug mode ( server) : true 
 Debug mode ( client) : false 
 Fds: 10
 Goroutines: 11
 EventsListeners: 0
 Init Path: /usr/local/bin/docker
 Docker Root Dir: /mnt/sda1/var/lib/docker
 
 docker@boot2docker:~$  ps aux |  grep [ /] usr/local/bin/docker
 690  root     /usr/local/bin/docker -d -D -g /var/lib/docker -H unix:// -H tcp://0.0.0.0:2376 --tlsverify --tlscacert= /var/lib/boot2docker/tls/ca.pem --tlscert= /var/lib/boot2docker/tls/server.pem --tlskey= /var/lib/boot2docker/tls/serverkey.pem
从docker的后台进程可以看到,后台服务监听2376端口,同时支持tls加密协议。
Docker的官方镜像的入口在Docker Hub Registry ,镜像文件放在了亚马逊AWS上,这对于国内的用户就比较悲剧了,因为要么是访问不到镜像文件,要么就是下载太慢。万幸的是,国内现在已经有了docker registry 的mirror - docker.cn 。
所以在pull或者运行容器的时候,需要在镜像前加上registry的ip或者主机名。我觉得更好的方式是可以将registry写在配置文件中,这样可以避免这个麻烦,不过目前还没有看到这样的解决方案。
So
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
docker@boot2docker:~$  docker run -i -t docker.cn/docker/ubuntu /bin/bash
 Unable to find image 'docker.cn/docker/ubuntu:latest'  locally
 Pulling repository docker.cn/docker/ubuntu
 8eaa4ff06b53: Download complete 
 511136ea3c5a: Download complete 
 3b363fd9d7da: Download complete 
 607c5d1cca71: Download complete 
 f62feddc05dc: Download complete 
 Status: Downloaded newer image for  docker.cn/docker/ubuntu:latest
 root@0b8874d6f2c8:/#
 
这条命令的意思是保持标准输入打开状态-i,并且Docker要为容器分配一个伪终端(tty)-t。Docker daemon首先在本地寻找名为docker.cn/docker/ubuntu的镜像,找不到的话,在去docker.cn下载。
从镜像下载的方式我们大概可以判断整个镜像是分层的,像git一样有版本管理,这个就是aufs文件系统的作用。镜像下载完成,容器启动后执行了bash命令,可以认为是来到了容器运行的操作系统中。
之后就可以像使用一个Ubuntu系统一样去使用这个容器了。
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
root@0b8874d6f2c8:/# ip a
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536  qdisc noqueue state UNKNOWN group default
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 valid_lft forever preferred_lft forever
 inet6 ::1/128 scope host
 valid_lft forever preferred_lft forever
 6: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500  qdisc noqueue state UP group default
 link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
 inet 172.17.0.2/16 scope global eth0
 valid_lft forever preferred_lft forever
 inet6 fe80::42:acff:fe11:2/64 scope link
 valid_lft forever preferred_lft forever
 
可以看到容器有自己的eth0网络设备以及由Docker分配的一个ip地址,和host machine没太大区别。
1 
2 
3 
root@0b8874d6f2c8:/# vim
 bash: vim: command  not found
 root@0b8874d6f2c8:/# apt-get install -y vim
 
没有vim,赶快装一个。
随之退出控制台,容器也停止运行。
1 
2 
3 
4 
5 
docker@boot2docker:~$  docker ps
 CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
 docker@boot2docker:~$  docker ps -l
 CONTAINER ID        IMAGE                           COMMAND             CREATED             STATUS                          PORTS               NAMES
 0b8874d6f2c8        docker.cn/docker/ubuntu:14.04   "/bin/bash"          15  hours ago        Exited ( 0)  About a minute ago                       naughty_darwin
 
使用docker ps命令可以查看运行时的容器,对于停止的容器,可以通过 docker ps -l 或者 docker ps -a可以看到所有的容器。
容器启动时通过--name选项可以指定容器的名字,缺省会随机给出一个名字,很诡异的一个设计,不能理解。
有名字的好处就是就是容易记忆或者查看,否则如果只能按照containerid那串hash code使用,想来就有些头大。
重新启动停止的容器
1 
2 
3 
4 
5 
docker@boot2docker:~$  docker start 0b8874d6f2c8
 0b8874d6f2c8
 docker@boot2docker:~$  docker ps
 CONTAINER ID        IMAGE                           COMMAND             CREATED             STATUS              PORTS               NAMES
 0b8874d6f2c8        docker.cn/docker/ubuntu:14.04   "/bin/bash"          15  hours ago        Up 3  seconds                            naughty_darwin
 
通过docker attach命令可以重新连接到容器上。
1 
2 
3 
docker@boot2docker:~$  docker attach 0b8874d6f2c8
 root@0b8874d6f2c8:/# which vim
 /usr/bin/vim
 
上次安装的vim依然在,可见docker保存了容器的状态(persistence)。
前面所创建的容器是交互式的容器,而实际的使用当中,我们需要容器去运行程序或者服务,这种又称为daemonized container. 下面是一个简单的例子:
1 
2 
3 
4 
5 
docker@boot2docker:~$  docker run --name awesomeness -d ubuntu /bin/sh -c "while :; do echo hello; sleep 5; done" 
 1bda4fdc3a3b869d1dc58bb4564b08e1bc0c0f24372f48afb8bcc4291cc94929
 docker@boot2docker:~$  docker ps
 CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
 1bda4fdc3a3b        ubuntu:latest       " /bin/sh -c ' while  :   55  seconds ago      Up 54  seconds                           awesomeness
 
使用docker logs命令可以查看容器的日志:
1 
2 
3 
4 
5 
6 
7 
docker@boot2docker:~$  docker logs awesomeness
 hello
 hello
 hello
 hello
 hello
 hello
 
加上-t选项可以输出时间戳,-f跟踪最新的日志:
1 
2 
3 
4 
5 
6 
docker@boot2docker:~$  docker logs -ft awesomeness
 2015-01-17T13:17:43.827474614Z hello
 2015-01-17T13:17:48.842826627Z hello
 2015-01-17T13:17:53.847642897Z hello
 2015-01-17T13:17:58.856081585Z hello
 2015-01-17T13:18:03.863587257Z hello
 
查看容器内的进程:
1 
2 
3 
4 
docker@boot2docker:~$  docker top awesomeness
 PID                 USER                COMMAND
 922                  root                /bin/sh -c while  :;  do  echo  hello;  sleep 5;  done 
1454                 root                sleep 5
通过Docker在容器内部启动新的进程,执行新的任务:
1 
2 
3 
4 
docker@boot2docker:~$  docker exec  -d awesomeness touch /tmp/testfile
 docker@boot2docker:~$  docker exec  -t -i  awesomeness  /bin/bash
 root@1bda4fdc3a3b:/# ls -al /tmp/testfile
 -rw-r--r-- 1  root root 0  Jan 17  14:03 /tmp/testfile
 
不得不说docker的发展真的很快,我最开始使用的时候docker的版本大概是在0.6,当时的容器技术还是使用lxc,
只能用lxc attach命令才能连接到运行的容器的控制台。现在使用这么简单,必须要点个赞。
停止运行的容器:
1 
docker stop awesomeness   # 用containerid 1bda4fdc3a3b 效果相同 
 
在容器意外退出时,自动重启容器:
1 
docker@boot2docker:~$  docker run --restart= always --name awesomeness -d ubuntu /bin/sh -c "while :; do echo hello; sleep 5; done" 
 
还可以设置重启的次数,--restart=on-failure:5。这个功能也很不错,让容器拥有了一定的自恢复(self-healing)能力,
查看容器的信息:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
docker@boot2docker:~$  docker inspect awesomeness
 [{ 
  "AppArmorProfile" : "" ,
   "Args" : [ 
   "-c" ,
   "while :; do echo hello; sleep 5; done" 
   ] ,
   "Config" : { 
     "AttachStderr" : false ,
     "AttachStdin" : false ,
     "AttachStdout" : false ,
     "Cmd" : [ 
     "/bin/sh" ,
     "-c" ,
     "while :; do echo hello; sleep 5; done" 
     ] ,
     "CpuShares" : 0,
     "Cpuset" : "" ,
     "Domainname" : "" ,
     "Entrypoint" : null,
 ........
 
inspect可以返回JSON格式的详细配置信息,不过这个信息略多,通过--format可以格式化输出的内容,假设我只想看到容器的IP地址:
1 
2 
docker@boot2docker:~$  docker inspect --format ''  awesomeness
 172.17.0.3
 
有点像调用了jq命令。
删除容器的命令是docker rm CONTAINER_ID or CONTAINER_NAME,这个操作只能针对已经停止运行的容器。删除所有容器的命令是:
1 
docker rm ` docker ps -a -q` 
 
这个命令会返回所有容器的ID,然后执行删除操作。实际的使用中我们可能只是删除部分的容器,可能就得结合cut,grep或者awk等命令来拿到要删除的容器ID/名字,然后再去执行删除操作。