解决容器设置问题的五大必备命令
遵循了教程,运行了Docker Run,然后……什么都没有发生。容器立即退出。或者它正在运行,但localhost只显示“无法访问此网站”。我们都经历过这种情况。当你刚接触Docker时,失败的容器感觉像一个密封的黑匣子。你知道里面出了问题,但不知道如何查看。
在这个快速指南中,我将展示五个基本命令来打开那个盒子,查看发生了什么,并修复你损坏的容器。
“损坏的应用程序”及其修复方法
为了帮助开发者调试他们的设置,让我们从一个有错误的Python小应用程序开始,看看如何进一步调试。以下是相关文件:
app.py
|
|
Dockerfile
|
|
构建以检查失败:
|
|
什么也看不到,直接返回到命令提示符。不幸的是,容器没有启动。让我们开始调试以检查错误。
1. docker ps -a:检查运行的Docker进程
首先要尝试的是运行:docker ps来检查容器。
|
|
这是初学者遇到的第一个陷阱。docker ps只显示当前运行的容器。由于我们的应用程序失败并停止,它不会出现在列表中。
要运行的命令是docker ps -a(这将显示运行/停止的容器)。
|
|
这揭示了我们可以用来进一步调试的某些信息。我们可以看到我们的my-broken-app容器。查看STATUS列:Exited (1) 8 seconds ago。这意味着容器确实运行了,但是其中的主进程(我们的python App.py命令)失败并以非零状态码退出(这表明有错误)。
何时使用:当容器似乎没有启动时,立即使用docker ps -a。它将确认它是否失败,或者(在另一种常见情况下)它是否正在运行,但你的run命令中存在端口转发问题(PORTS列将为空)。
2. docker logs [container_id]:“哪里出错了"命令
好的,我们知道容器失败了。现在我们需要知道原因。
每个容器都有自己的日志流,捕获其主进程的标准输出(stdout)和标准错误(stderr)。docker logs让你读取它。
从docker ps -a命令获取CONTAINER ID(或NAMES)并在此处使用:
|
|
输出:
|
|
在这里我们看到了问题。错误不是一些复杂的问题;而是一个简单且相当熟悉的"文件未找到"错误。我们的CMD有bug。
何时使用:当容器具有EXITED状态时使用docker logs。使用它来了解失败的原因和方式。
3. docker exec -it [container_id] /bin/sh:窥视容器内部
让我们修复我们的Dockerfile(将App.py更改为app.py)并重新构建:docker build -t my-fixed-app .
如果我们遇到不同的问题怎么办?如果容器正在工作但应用程序不工作(例如,localhost:3000显示"500内部服务器错误”)。
|
|
它启动了,但不工作。我们如何"进入"其中探查?
使用docker exec。此命令允许你在已运行的容器内运行新进程。在这种情况下,我们将使用它来运行简单的shell命令。
- exec:执行新命令。
- -it:代表"交互式终端"。这将把你的键盘和屏幕附加到正在运行的容器。
- [container_id]:运行容器的ID(例如,a3f9a0c3b7e8)。
- /bin/sh:这是我们要运行的命令(一个简单的Shell命令)。(/bin/bash和/bin/sh常用)。
|
|
你正在查看容器内部!那个#显示它在容器的文件系统中:
/app #ls -l:列出文件以及相关权限。/app #cat app.py:显示本地文件以检查内容是否正常。/app #env:检查环境变量。/app #ps aux:检查Python进程是否工作。
何时使用:当容器已启动并运行但应用程序不正常时使用此命令。这非常强大,将在调试实际问题时提供很大帮助。
4. docker run -it –entrypoint /bin/sh [image_id]:“覆盖"命令
这是一个非常巧妙的技巧。如果你的容器失败得如此之快(像我们的第一个my-broken-app示例),以至于你无法exec进入它,并且日志太糟糕以至于你无法使用它来调试。
实际上,Docker有一个有用的命令来覆盖Dockerfile中的CMD或ENTRYPOINT。
|
|
让我们分解一下:
- run -it:以交互模式启动新容器。
- –entrypoint /bin/sh:这是命令。它告诉Docker忽略Dockerfile中的CMD(python App.py部分)。相反,它只运行shell。
- my-broken-app:我们要检查的镜像。
它会将你放入从损坏镜像构建的全新容器内的shell中。它使你能够与文件系统交互,就像CMD即将运行时一样。现在你可以运行ls -l并看到"A-ha!文件是app.py,但我的CMD调用的是App.py。“通过探索镜像本身,你找到了bug。
何时使用:当容器无法启动且Docker日志不清晰时,使用此"覆盖"命令。它是进入任何镜像的万能钥匙。
5. docker system prune:清理僵尸内容的清理命令
随着所有运行的损坏应用程序,将有许多来自旧失败构建的悬空镜像。一些镜像可能很大,占用千兆字节的磁盘空间。
回顾:
docker ps -a显示所有容器。docker image ls显示所有镜像,包括标记为<none>的镜像(这些是悬空镜像)。
你可以通过docker rm [id]逐个删除容器,docker rmi [id]删除镜像。但是,有一个更简单的方法。
|
|
它将安全地清理本地设置中的所有悬空内容。
何时运行:在开发会话后运行docker system prune以回收磁盘空间并保持环境清洁。
完整的调试工作流程
以下是整个工作流程的回顾:
- 对于容器失败:运行
docker ps -a查找容器并查看"EXITED"状态列以精确定位问题。 - 检查错误日志:运行
docker logs [container_id]查找并了解容器的错误日志。 - 如果应用程序不工作时的探索内容:
- 如果容器没有启动,运行
docker run -it --entrypoint /bin/sh [image_id]探索本地文件系统。 - 如果容器正在运行但有bug,应用程序运行不正常,运行
docker exec -it [container_id] /bin/sh{bash}以进行调试。
- 如果容器没有启动,运行
- 修复和重建:修复代码和Dockerfile并再次构建容器。
- 清理:运行
docker system prune清除所有悬空内容。