我遇到了一个容器问题,即使它构建得很好,它也没有正确启动。原因是我添加到 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
$
日志中没有任何内容,我也无法调用交互式 shell。我可以使用 strace 来查看发生了什么,但我希望有更好的方法。
有什么办法可以让 docker 更详细吗?
编辑:感谢 Andrew D。我现在知道上面的代码有什么问题(我留下了它,以便可以理解他的答案)。现在的问题仍然是我如何调试这样的东西或了解为什么ls -l失败了为什么ls没有。
编辑: -D=true 可能会提供更多输出,但在我的情况下不是...
Docker
events
命令可能会有所帮助,即使在映像无法启动后, Docker logs命令也可以获取日志。首先
docker events
在后台启动,看看发生了什么。然后运行失败的
docker run ...
命令。然后您应该在屏幕上看到类似以下内容:然后您可以从上一条消息或运行命令的输出中获取启动十六进制 id。然后你可以将它与 logs 命令一起使用:
您现在应该会看到来自失败的映像启动的一些输出。
正如@alexkb 在评论中建议的那样:
docker events&
如果您的容器不断地从 AWS ECS 服务之类的东西重新启动,这可能会很麻烦。在这种情况下,从日志中获取容器十六进制 id 可能更容易/var/log/ecs/ecs-agent.log.<DATE>
。然后使用 dockerlogs <hex id>
。到目前为止,我发现的最好的是:
刚刚从一个新的 shell 启动客户端。误解是认为客户端实际上做了任何事情......好吧,它只是与守护进程通信,所以你不想调试客户端而是调试守护进程本身(通常)。
就我而言,
-a
(附加到 STDOUT/STDERR)标志就足够了:它显示了启动错误(在我们的例子中,缺少使用的日志路径
supervisord
)。我认为大多数容器启动错误也会出现在这里。我无法回答您关于如何使 docker 输出更完整的问题,但我可以告诉您,就地正则表达式替换 .so 文件中的字符串有点疯狂:字符串只分配了这么多空间,并且如果更改其他条目的文件偏移量,elf 文件将损坏。在容器外部运行 perl 命令(在 LD_LIBRARY_PATH 更改之前)后,尝试在 .so 文件上运行 objdump 或 readelf —— 美元到甜甜圈现在已损坏。
它在这个非常必要的 hack中起作用的原因是因为“tmp”和“etc”是相同的字符串长度,所以没有偏移量改变。如果您不想使用 /tmp,请考虑目录 /dkr 或类似目录。
如果您必须采用这种方法并且您所需的路径不可更改,请重建库并更改源中 /etc/hosts 的默认路径。或者更好的是,在构建修改后的
libnss_files.so
重命名时,将其重命名为类似libnss_altfiles.so
并更改nsswitch.conf
为hosts: altfiles
在启动 docker 容器时使用(除非 docker 也绑定了挂载的 nsswitch.conf,否则您无法更改它)。这将使您拥有 libnss_altfiles.so 与基本系统中的普通库并行。如果 docker 确实绑定挂载 nsswitch.conf,请在 /lib-override 目录中保留重建的 libnss_files.so 的副本,以供 LD_LIBRARY_PATH 加载。提醒一下,suid/sgid 二进制文件会忽略 LD_LIBRARY_PATH 和 LD_PRELOAD,因此如果您使用这些变量,有些东西会被破坏(阅读:返回使用默认的 /etc/hosts)。
有时,您可以通过 ssh 进入运行 docker 守护进程的节点然后执行以下操作来找到有用的错误消息:
在 Mac OS 上的“Docker 社区版”上,您可以通过以下方式连接到 docker vm: