如何知道 Docker 容器退出的原因?

164

我有一个运行在1G RAM主机上的Docker容器(同一台主机还运行着其他容器)。 这个Docker容器中的应用程序将解码一些图像,这可能会消耗大量内存。

不时地,这个容器会退出。我怀疑是因为内存不足,但不是很确定。我需要一种方法来找到根本原因。那么有没有办法知道这个容器退出的原因?


13
您可以通过使用 docker logs <容器ID> 命令来查看该容器的日志。 - techtabu
5
但是容器已经退出,我猜我不能再记录它的日志了? - Li Bin
你的问题的答案是否定的。如果容器死亡,应用程序也会死亡。 - techtabu
请注意,如果您想返回并检查一个已停止的容器,您可以使用 docker commit <containerid> my_temp_image 将其提交为镜像,然后运行 docker run -it --entrypoint /bin/bash my_temp_image 以在其中获取 shell。如果有任何日志、杂项文件或其他留下来的东西需要检查,它们都会在那里。当然,这是假设您的镜像中有 bash。 - Giftiger Wunsch
有些人可能需要注意,如果您使用“删除”选项运行 docker run --rm ... 命令,那么容器在退出后将被删除,这就是您无法获取日志的原因。您仍然可以从“死亡”容器中访问日志,除非您将其删除(或自动删除)。只需摆脱 --rm 选项即可。 - Mikaelblomkvistsson
显示剩余7条评论
5个回答

192

其他人已经提到了docker logs $container_id来查看应用程序的输出。这总是我首先要检查的事情。

接下来,您可以运行docker inspect $container_id以查看状态的详细信息,例如:

    "State": {
        "Status": "exited",
        "Running": false,
        "Paused": false,
        "Restarting": false,
        "OOMKilled": false,
        "Dead": false,
        "Pid": 0,
        "ExitCode": 2,
        "Error": "",
        "StartedAt": "2016-06-28T21:26:53.477229071Z",
        "FinishedAt": "2016-06-28T21:26:53.478066987Z"
    },

重要的一行是“OOMKilled”,如果您超过容器内存限制,Docker将杀死您的应用程序。您还可以查找退出代码,以查看是否确定了应用程序退出的原因。

请注意,这仅指示docker本身是否杀死了您的进程,并且需要在容器上设置内存限制。在docker之外,如果主机本身耗尽内存,Linux内核可能会终止您的进程。当此情况发生时,Linux通常会在/var/log中写入日志。在Windows和Mac上使用Docker桌面版,您可以在Docker设置中调整分配给嵌入式Linux虚拟机的内存。


17
我不明白,既然我的容器消失了,那么“inspect”怎么工作?从上面的讨论中可以看出,一旦应用程序死亡,容器也会死亡。您的意思是重新启动相同的映像然后检查吗? - Li Bin
14
当容器停止运行时,它并不会被擦除,而是进入一种停滞状态,例如状态为stopped或exited。可以使用命令“docker ps -a”查看容器的状态。 - Samuel Toh
每次运行内存密集型操作时,我都会得到“exit 0”的结果,并且OOMKilled为false。增加内存后再次运行,程序就能正常工作了。 - Andrei
1
如果Linux内核而不是Docker引擎杀死容器中的进程,就会发生这种情况。您经常会在主机上的/var/log操作系统日志中看到这一点。 - BMitch
2
我知道这是一个打字错误,但是Linux内核“lol”你的进程似乎非常合适。 - Jim T
这个能让我少折腾两天啊!我的容器只会显示“已退出”,而实际日志里什么都没有。只有在检查输出后才发现它被 OOMKilled 了。为什么 Docker 不把状态标记为 OOMKilled 而是 EXITED 呢? - Ebsan

12

通过阅读日志,您可以查看容器内的进程是否被OOMkilled。内核会启动OOMkill,因此每次发生时,/var/log/kern.log中都会有一堆行,例如:

python invoked oom-killer: gfp_mask=0x14000c0(GFP_KERNEL), nodemask=(null), order=0, oom_score_adj=995
oom_kill_process+0x22e/0x450
Memory cgroup out of memory: Kill process 31204 (python) score 1994 or sacrifice child
Killed process 31204 (python) total-vm:7350860kB, anon-rss:4182920kB, file-rss:2356kB, shmem-rss:0kB

这个答案帮助我找到了一个容器的问题,它在退出时会重新启动(docker inspect 在这里并没有太大帮助)。 - m90

9

尽管被接受的答案是最佳选择,但有时从主机检查日志内容也很有用(在Linux上)。

您可以通过输入以下命令来实现:

sudo journalctl -u docker

或者追踪它
sudo journalctl -u docker -f

或者将输出导向到
sudo journalctl -xn -u docker | less

1
就是这样!太棒了。Docker 中没有任何日志,但这向我展示了某些东西杀死并重新启动了守护进程。 - oligofren

0

docker inspect -f '{{ .State }}' $container_id 并检查第8个属性,即ExitCode。


0

如果您无法访问容器的日志,特别是当您使用Docker API时 - 例如因为docker.errors.NotFound: 404 Client Error - 原因可能是容器在退出后被自动删除了。

这可能是由于使用docker run --rm选项运行容器引起的,该选项是:自动删除容器退出时的容器。然后您将无法再获取日志。

只需摆脱--rm选项,并在收集日志后手动删除容器即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接