如何调试Docker容器初始化?


92

我对容器有问题,即使它构建完美,也无法正常启动。原因是我已添加到Dockerfile中的解决方法(因为具有自配置的/ etc / hosts路由)

RUN mkdir -p -- /lib-override /etc-override && cp /lib/libnss_files.so.2 /lib-override
ADD hosts.template /etc-override/hosts
RUN perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override

显然那里有一些错误,但是我想知道如何在运行时获取有关docker正在做什么的更多信息。例如,这有效:

$ docker run image ls
usr bin ...

但这不是:

$ docker run image ls -l
$

日志中没有任何内容,我也无法调用交互式外壳。我可以使用strace看看发生了什么,但我希望有更好的方法。

有什么方法可以将docker设置为更详细?

编辑:感谢安德鲁·D。我现在知道上面的代码有什么问题(我把它留了下来,所以他的回答可以理解)。现在的问题仍然是我如何调试这样的东西,或者深入了解为什么ls -l失败,而ls没有失败。

编辑:-D = true可能会提供更多输出,尽管在我来说不是...


请努力将答案之一标记为“已接受”,谢谢!
Brian Topping

Answers:


94

Docker events命令可能会有所帮助,即使映像无法启动,Docker日志命令也可以获取日志。

首先从docker events后台开始,看看发生了什么。

docker events&

然后运行失败的docker run ...命令。然后,您应该在屏幕上看到以下内容:

2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die

然后,您可以从上一条消息或run命令的输出中获取启动十六进制ID。然后,可以将其与logs命令一起使用:

docker logs <copy the instance id from docker events messages on screen>

现在,您应该看到失败的映像启动的一些输出。

正如@alexkb在评论中建议的那样:docker events&如果您的容器不断从诸如AWS ECS服务之类的东西重新启动,可能会很麻烦。在这种情况下,从登录中获取容器的十六进制ID可能会更容易/var/log/ecs/ecs-agent.log.<DATE>。然后使用docker logs <hex id>


很有帮助!docker的新手,正试图使portainer运行。通过以下调试步骤解决了该问题。在Medium.com上发现了具有相同问题的某人:medium.com/@jameson_37151/…–
Jameson

我得到“找不到容器”!?
痴呆的刺猬

奇怪。为了确保,@ dementedhedgehog是否尝试从以“ (from xxx/xxx:latest) die” 结尾的日志消息中复制十六进制ID ?
彼得·兰伯格

1
非常感谢您的回答,这可以节省生命。docker events&如果要不断从AWS ECS服务之类的容器中不断重启容器,那么唯一要添加的就是麻烦。因此,在这种情况下,从登录中获取容器的十六进制ID可能会更容易/var/log/ecs/ecs-agent.log.<DATE>。然后docker logs <hex id>按照此答案的建议使用,以查看为什么无法启动。
alexkb '18

1
@alexkb谢谢!我将您的建议添加到答案的末尾,以便其他人可以更轻松地找到它。
彼得·兰伯格

18

好吧,到目前为止我发现的最好的是:

#stop the current demon and start it in debug modus
sudo service docker stop
dockerd -D # --debug

刚从新的外壳启动客户端。误解是认为客户端实际上可以执行任何操作……好吧,它只是与守护程序通信,因此您不想调试客户端,而要调试守护程序本身(通常)。


13

就我而言,-a(附加到STDOUT / STDERR)标志就足够了:

user@machine:~$ docker start -a server_name
Error: The directory named as part of the path /log/log_path/app.log does not exist.
For help, use /usr/bin/supervisord -h

它显示了启动错误(在我们的例子中,缺少了使用的日志路径supervisord)。我假设大多数容器启动错误也会在此处显示。


3

我无法回答有关如何使docker输出更完整的问题,但我可以告诉您,就地正则表达式替换.so文件中的字符串有点疯狂:该字符串仅分配了太多空间,并且如果更改其他条目的文件偏移,则elf文件将损坏。在容器外部运行perl命令(在LD_LIBRARY_PATH更改之前)后,请尝试在.so文件上运行objdump或readelf- 美元现在已经损坏了。

它之所以在这种可悲的必要技巧中起作用是因为“ tmp”和“ etc”具有相同的字符串长度,因此偏移量没有变化。如果您不想使用/ tmp,请考虑使用目录/ dkr或类似目录。

如果必须采用这种方法,并且所需的路径不可更改,请重建库并更改源中/ etc / hosts的默认路径。或者更好的libnss_files.so做法是,在构建修改后的名称时,将其重命名为类似名称,libnss_altfiles.so并在启动Docker容器时更改nsswitch.conf为使用hosts: altfiles(除非Docker也绑定了已挂载的nsswitch.conf,否则您将无法进行更改)。这样,您就可以将libnss_altfiles.so与基本系统中的常规库并行运行。如果docker确实绑定了nsswitch.conf,请将重建的libnss_files.so的副本保留在/ lib-override目录中,以供LD_LIBRARY_PATH加载。

请注意,suid / sgid二进制文件会忽略LD_LIBRARY_PATH和LD_PRELOAD,因此,如果使用这些变量,则有些东西会中断(阅读:返回使用默认的/ etc / hosts)。


非常感谢您的深刻见解...我太快了,现在看看发生了什么。我仍然不知道为什么要获取统计信息需要解析主机(ls -l),而简单文件列表(ls)却不...
estani 2014年

0

有时,您可以通过切入运行docker守护程序的节点然后执行以下操作来找到有用的错误消息:

$ tail -f /var/log/containers/* /var/log/docker.log 2>&1

在Mac OS上的“ Docker社区版本”上,您可以通过执行以下操作连接到docker vm:

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.