8 容器内部都在干些什么

现在我们已经有了一个在后台运行 while 循环的守护型容器。为了探究该容器内部都在干些什么,可以用 docker logs 命令来获取容器的日志,如代码清单3-19所示。

代码清单3-19 获取守护式容器的日志

$ sudo docker logs daemon_dave
hello world
hello world
hello world
hello world
hello world
hello world
hello world
. . .

这里,我们可以看到 while 循环正在向日志里打印 hello world 。Docker会输出最后几条日志项并返回。我们也可以在命令后使用 -f 参数来监控Docker的日志,这与 tail -f 命令非常相似,如代码清单3-20所示。

代码清单3-20 跟踪守护式容器的日志

$ sudo docker logs -f daemon_dave
hello world
hello world
hello world
hello world
hello world
hello world
hello world
. . .

提示

可以通过Ctr+C退出日志跟踪。

我们也可以跟踪容器日志的某一片段,和之前类似,只需要在 tail 命令后加入 -f --tail 标志即可。例如,可以用 docker logs --tail 10 daemon_dave 获取日志的最后10行内容。另外,也可以用 docker logs --tail 0 -f daemon_dave命令来跟踪某个容器的最新日志而不必读取整个日志文件。

为了让调试更简单,还可以使用 -t 标志为每条日志项加上时间戳,如代码清单3-21所示。

代码清单3-21 跟踪守护式容器的最新日志

$ sudo docker logs -ft daemon_dave
[May 10 13:06:17.934] hello world
[May 10 13:06:18.935] hello world
[May 10 13:06:19.937] hello world
[May 10 13:06:20.939] hello world
[May 10 13:06:21.942] hello world
. . .

提示

同样,可以通过Ctr+C退出日志跟踪。

9 Docker日志驱动

自Docker 1.6开始,也可以控制Docker守护进程和容器所用的日志驱动,这可以通过--log-driver选项来实现。可以在启动Docker守护进程或者执行docker run命令时使用这个选项。

有好几个选项,包括默认的json-file,json-file也为我们前面看到的docker logs命令提供了基础。

其他可用的选项还包括syslog,该选项将禁用docker logs命令,并且将所有容器的日志输出都重定向到Syslog。可以在启动Docker守护进程时指定该选项,将所有容器的日志都输出到Syslog,或者通过docker run对个别的容器进行日志重定向输出。

代码清单3-22 在容器级别启动Syslog

$ sudo docker run --log-driver="syslog" --name daemon_dwayne -d
  ubuntu /bin/sh -c "while true; do echo hello world; sleep 1;
  done"
. . .

提示

如果是在Docker Toolbox中运行Docker,应该在虚拟机中启动Syslog守护进程。可以先通过docker-machine ssh命令连接到Docker Toolbox虚拟机,再在其中运行syslogd命令来启动Syslog守护进程。

上面的命令会将daemon_dwayne容器的日志都输出到Syslog,导致docker logs命令不输出任何东西。

最后,还有一个可用的选项是none,这个选项将会禁用所有容器中的日志,导致docker logs命令也被禁用。

提示

新的日志驱动也在不断地增加,在Docker 1.8中,新增了对Graylog GELF协议、Fluentd以及日志轮转驱动的支持。

10 查看容器内的进程

除了容器的日志,也可以查看容器内部运行的进程。要做到这一点,要使用docker top 命令,如代码清单3-23所示。

代码清单3-23 查看守护式容器的进程

$ sudo docker top daemon_dave

该命令执行后,可以看到容器内的所有进程(主要还是我们的 while 循环)、运行进程的用户及进程ID,如代码清单3-24所示。

代码清单3-24 docker ** top 命令的输出结果

PID USER COMMAND
977 root /bin/sh -c while true; do echo hello world; sleep 1;
  done
1123 root sleep 1

11 Docker统计信息

除了 docker top 命令,还可以使用 docker stats 命令,它用来显示一个或多个容器的统计信息。让我们来看看它的输出是什么样的。下面我们来查看一下容器daemon_dave 以及其他守护式容器的统计信息。

代码清单3-25 docker stats命令

$ sudo docker stats daemon_dave daemon_kate daemon_clare daemon_sarah
CONTAINER     CPU %  MEM USAGE/LIMIT  MEM %  NET I/O           BLOCK I/O
daemon_clare 0.10%  220 KiB/994 MiB  0.02%  1.898 KiB/648 B 12.75 MB / 0 B
daemon_dave  0.14%  212 KiB/994 MiB  0.02%  5.062 KiB/648 B 1.69   MB / 0 B
daemon_kate  0.11%  216 KiB/994 MiB  0.02%  1.402 KiB/648 B 24.43  MB / 0 B
daemon_sarah 0.12%  208 KiB/994 MiB  0.02%  718 B/648 B      11.12  MB / 0 B

我们能看到一个守护式容器的列表,以及它们的CPU、内存、网络I/O及存储I/O的性能和指标。这对快速监控一台主机上的一组容器非常有用。

注意

docker stats是Docker 1.5.0中引入的命令。

12 在容器内部运行进程

在Docker 1.3之后,也可以通过 docker exec 命令在容器内部额外启动新进程。可以在容器内运行的进程有两种类型:后台任务和交互式任务。后台任务在容器内运行且没有交互需求,而交互式任务则保持在前台运行。对于需要在容器内部打开shell的任务,交互式任务是很实用的。下面先来看一个后台任务的例子,如代码清单3-26所示。

代码清单3-26 在容器中运行后台任务

$ sudo docker exec -d daemon_dave touch /etc/new_config_file

这里的 -d 标志表明需要运行一个后台进程, -d 标志之后,指定的是要在内部执行这个命令的容器的名字以及要执行的命令。上面例子中的命令会在 daemon_dave容器内创建了一个空文件,文件名为 /etc/new_config_file 。通过 docker exec 后台命令,可以在正在运行的容器中进行维护、监控及管理任务。

提示

从Docker 1.7开始,可以对docker exec启动的进程使用–u标志为新启动的进程指定一个用户属主。

我们也可以在 daemon_dave 容器中启动一个诸如打开shell的交互式任务,如代码清单3-27所示。

代码清单3-27 在容器内运行交互命令

$ sudo docker exec -t -i daemon_dave /bin/bash

和运行交互容器时一样,这里的 -t 和 -i 标志为我们执行的进程创建了TTY并捕捉 STDIN 。接着我们指定了要在内部执行这个命令的容器的名字以及要执行的命令。在上面的例子中,这条命令会在 daemon_dave 容器内创建一个新的bash会话,有了这个会话,我们就可以在该容器中运行其他命令了。

注意

docker exec命令是Docker 1.3引入的,早期版本并不支持该命令。对于早期Docker版本,请参考第6章中介绍的nsenter命令。

13 停止守护式容器

要停止守护式容器,只需要执行 docker stop 命令,如代码清单3-28所示。

代码清单3-28 停止正在运行的Docker容器

$ sudo docker stop daemon_dave

当然,也可以用容器ID来指代容器名称,如代码清单3-29所示。

代码清单3-29 通过容器ID停止正在运行的容器

$ sudo docker stop c2c4e57c12c4

注意

docker stop命令会向Docker容器进程发送SIGTERM信号。如果想快速停止某个容器,也可以使用docker kill命令来向容器进程发送SIGKILL信号。

要想查看已经停止的容器的状态,则可以使用 docker ps 命令。还有一个很实用的命令 docker ps -n x ,该命令会显示最后 x 个容器,不论这些容器正在运行还是已经停止。

14 自动重启容器

如果由于某种错误而导致容器停止运行,还可以通过 --restart 标志,让Docker自动重新启动该容器。 --restart 标志会检查容器的退出代码,并据此来决定是否要重启容器。默认的行为是Docker不会重启容器。

代码清单3-30是一个在 docker run 命令中使用 —restart 标志 的例子。

代码清单3-30 自动重启容器

$ sudo docker run --restart=always --name daemon_dave -d ubuntu /
  bin/sh -c "while true; do echo hello world; sleep 1; done"

在本例中, --restart 标志被设置为 always 。无论容器的退出代码是什么,Docker都会自动重启该容器。除了 always ,还可以将这个标志设为 on-failure,这样,只有当容器的退出代码为非0值的时候,才会自动重启。另外, on-failure``还接受一个可选的 重启次数参数,如代码清单3-31所示。

代码清单3-31 为 on-failure 指定 count 参数

--restart=on-failure:5

这样,当容器退出代码为非0时,Docker会尝试自动重启该容器,最多重启5次。

注意

--restart标志是Docker1.2.0引入的选项。

15 深入容器

除了通过 docker ps 命令获取容器的信息,还可以使用 docker inspect``来获得更多的容器信息,如代码清单3-32所示。

代码清单3-32 查看容器

$ sudo docker inspect daemon_dave
[{
    "ID": "
      c2c4e57c12c4c142271c031333823af95d64b20b5d607970c334784430bcbd0f
      ",
    "Created": "2014-05-10T11:49:01.902029966Z",
    "Path": "/bin/sh",
    "Args": [
    "-c",
    "while true; do echo hello world; sleep 1; done"
    ],
    "Config": {
      "Hostname": "c2c4e57c12c4",
. . .

docker inspect 命令会对容器进行详细的检查,然后返回其配置信息,包括名称、命令、网络配置以及很多有用的数据。

也可以用 -f 或者 --format 标志来选定查看结果,如代码清单3-33所示。

代码清单3-33 有选择地获取容器信息

$ sudo docker inspect --format='{{ .State.Running }}' daemon_dave
false

上面这条命令会返回容器的运行状态,示例中该状态为 false 。我们还能获取其他有用的信息,如容器IP地址,如代码清单3-34所示。

代码清单3-34 查看容器的IP地址

$ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}'
    daemon_dave
172.17.0.2

提示

--format或者-f标志远非表面看上去那么简单。该标志实际上支持完整的Go语言模板。用它进行查询时,可以充分利用Go语言模板的优势。

也可以同时指定多个容器,并显示每个容器的输出结果,如代码清单3-35所示。

代码清单3-35 查看多个容器

$ sudo docker inspect --format '{{.Name}} {{.State.Running}}' \
daemon_dave bob_the_container
/daemon_dave false
/bob_the_container false

可以为该参数指定要查询和返回的查看散列(inspect hash)中的任意部分。

注意

除了查看容器,还可以通过浏览/var/lib/docker目录来深入了解Docker的工作原理。该目录存放着Docker镜像、容器以及容器的配置。所有的容器都保存在/var/lib/docker/containers目录下。

16 删除容器

如果容器已经不再使用,可以使用 docker rm 命令来删除它们,如代码清单3-36所示。

代码清单3-36 删除容器

$ sudo docker rm 80430f8d0921
80430f8d0921

注意

从Docker 1.6.2开始,可以通过给docker rm命令传递-f标志来删除运行中的Docker容器。这之前的版本必须先使用docker stop或docker kill命令停止容器,才能将其删除。

目前,还没有办法一次删除所有容器,不过可以通过代码清单3-37所示的小技巧来删除全部容器。

代码清单3-37 删除所有容器

$ sudo docker rm `sudo docker ps -a -q`

上面的 docker ps 命令会列出现有的全部容器, -a 标志代表列出所有容器,而-q 标志则表示只需要返回容器的ID而不会返回容器的其他信息。这样我们就得到了容器ID的列表,并传给了 docker rm 命令,从而达到删除所有容器的目的。


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐