我想用一个不同的命令启动一个已停止的Docker容器,因为默认命令崩溃 - 这意味着我无法启动容器,然后使用' docker exec'。
基本上我想启动一个shell,这样我就可以检查容器的内容了。
幸运的是我用-it选项创建了容器!
答案 0 :(得分:280)
docker ps -a
此命令将修改后的容器状态保存到新图像user/test_image
docker commit $CONTAINER_ID user/test_image
docker run -ti --entrypoint=sh user/test_image
入口点参数说明:https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime
上面的步骤只是启动一个具有相同文件系统状态的已停止容器。这对于快速调查非常有用。但是环境变量,网络配置,附加卷和其他人员不是继承的,您应该明确指定所有这些参数。
从这里借用了启动已停止容器的步骤:(最后评论)https://github.com/docker/docker/issues/18078
答案 1 :(得分:99)
编辑此文件(对应于已停止的容器):
vi /var/lib/docker/containers/923...4f6/config.json
更改"路径"参数指向新命令,例如/斌/庆典。您也可以设置" Args"将参数传递给命令的参数。
重新启动docker服务(注意这将停止所有正在运行的容器):
service docker restart
列出您的容器并确保命令已更改:
docker ps -a
启动容器并连接到它,你现在应该在你的shell中了!
docker start -ai mad_brattain
使用Docker 1.7.1在Fedora 22上工作。
注意:如果您的shell不是交互式的(例如,您没有使用-it选项创建原始容器),则可以将命令更改为" / bin / sleep 600&# 34;或" / bin / tail -f / dev / null"给你足够的时间去做#14; docker exec -it CONTID / bin / bash"作为获得shell的另一种方式。
注意2:较新版本的docker有config.v2.json,您需要更改Entrypoint或Cmd(感谢user60561)。
答案 2 :(得分:14)
Docker确实需要将其作为一项新功能实现,但这是另一种解决方法选项,用于在成功或失败后终止入口点的情况,这会使调试变得困难。
如果您还没有Entrypoint脚本,请创建一个运行容器所需命令的脚本。然后,在此文件的顶部,将这些行添加到entrypoint.sh
:
# Run once, hold otherwise
if [ -f "already_ran" ]; then
echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
cat
fi
touch already_ran
# Do your main things down here
要确保cat
保持连接,您可能需要提供TTY。我使用我的Entrypoint脚本运行容器,如下所示:
docker run -t --entrypoint entrypoint.sh image_name
这将导致脚本运行一次,创建一个指示它已经运行的文件(在容器的虚拟文件系统中)。然后,您可以重新启动容器以执行调试:
docker start container_name
当您重新启动容器时,将找到already_ran
文件,导致Entrypoint脚本停止cat
(它只会永远等待永远不会出现的输入,但保持容器处于活动状态) 。然后,您可以执行调试bash
会话:
docker exec -i container_name bash
当容器正在运行时,您还可以删除already_ran
并手动执行entrypoint.sh
脚本以重新运行它,如果您需要以这种方式进行调试。
答案 3 :(得分:1)
我接受了@Dmitriusan的回答并将其变成了别名:
alias docker-run-prev-container =' prev_container_id =" $(docker ps -aq | head -n1)" &安培;&安培; docker commit" $ prev_container_id" " prev_container / $ prev_container_id" &安培;&安培; docker run -it --entrypoint = bash" prev_container / $ prev_container_id"'
将此添加到您的~/.bashrc
别名文件中,您将拥有一个漂亮的新docker-run-prev-container
别名,它会将您放入上一个容器中的shell中。
有助于调试失败的docker build
s。
答案 4 :(得分:1)
我的问题:
docker run <IMAGE_NAME>
开始了一个容器docker ps -a
时,我可以看到两个容器。 docker run <IMAGE_NAME>
命令时,都会创建新图像解决方案: 要在您首先创建的同一容器上运行,请遵循以下步骤
docker ps
获取容器的容器docker container start <CONTAINER_ID>
以启动现有容器docker exec -it <CONTAINER_ID> /bin/bash
答案 5 :(得分:1)
我找到了一个简单的命令
docker start -a [container_name]
这个就行了
或
docker start [container_name]
然后
docker exec -it [container_name] bash
答案 6 :(得分:1)
对我来说,Docker 总是给人一种它是为一个业余爱好系统而创建的印象,它很适合这个。
如果某件事失败或不起作用,不要指望有专业的解决方案。
也就是说:Docker 不仅不支持这种基本的管理任务,它还试图阻止它们。
解决方案:
cd /var/lib/docker/overlay2/
find | grep somechangedfile
# You now can see the changed file from your container in a hexcoded folder/diff
cd hexcoded-folder/diff
创建一个 entrypoint.sh
(如果存在,请确保备份现有的)
cat > entrypoint.sh
#!/bin/bash
while ((1)); do sleep 1; done;
Ctrl+C
chmod +x entrypoint.sh
docker stop
docker start
你现在让你的 docker 容器运行一个无限循环而不是原来的条目,你可以 exec bash 进入它,或者做任何你需要的。 完成后停止容器,删除/重命名您的自定义入口点。
答案 7 :(得分:0)
没有指定容器是否正在退出,只是您的代码崩溃了,您需要查看容器中发生了什么。如果它没有退出,这是另一个潜在的解决方案。
使用docker ps
docker exec -it 665b4a1e17b6 /bin/sh
如果将入口点设置为有问题的东西,也可以按照Dmitriusan的回答中的建议覆盖它。还应注意,您可以使用docker attach
附加到任何正在运行的容器。这么多解决方案有不同的解我只是没有看到需要提交图像。这似乎没必要。
Docker exec的文档 - https://docs.docker.com/engine/reference/commandline/exec/
Docker附加文档 - https://docs.docker.com/engine/reference/commandline/attach/
答案 8 :(得分:0)
这并不是您所要的,但是如果您要检查文件,则可以在已停止的容器上使用docker export
。
mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
答案 9 :(得分:0)
似乎在容器启动后 docker 无法更改入口点。但是可以设置自定义入口点,下次重启时更改入口点的代码。
例如你运行一个这样的容器:
docker run --name c --entrypoint "/boot" -v "./boot":/boot $image
这里是启动入口点:
#!/bin/bash
command_a
当您需要使用不同的命令重新启动 c 时,您只需更改启动脚本:
#!/bin/bash
command_b
然后重启:
docker restart c
答案 10 :(得分:-11)
docker container start <CONTAINER_ID>
答案 11 :(得分:-12)
我实际上不同意这两个答案。如果您只想查看容器中的内容,则可以运行此命令来获取shell。无需更改入口点或任何配置。
docker run -it <image_name> bash