如何使用不同的命令启动已停止的Docker容器?

时间:2015-09-02 12:23:18

标签: docker

我想用一个不同的命令启动一个已停止的Docker容器,因为默认命令崩溃 - 这意味着我无法启动容器,然后使用' docker exec'。

基本上我想启动一个shell,这样我就可以检查容器的内容了。

幸运的是我用-it选项创建了容器!

12 个答案:

答案 0 :(得分:280)

找到已停止的容器ID

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)

将检查添加到Entrypoint脚本的顶部

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 不仅不支持这种基本的管理任务,它还试图阻止它们。

解决方案:

  1. cd /var/lib/docker/overlay2/
    
  2. find | grep somechangedfile 
    # You now can see the changed file from your container in a hexcoded folder/diff
    
  3. cd hexcoded-folder/diff
    
  4. 创建一个 entrypoint.sh(如果存在,请确保备份现有的)

    cat > entrypoint.sh
    #!/bin/bash
    while ((1)); do sleep 1; done;
    

    Ctrl+C

     chmod +x entrypoint.sh
    
  5. docker stop
    docker start
    

你现在让你的 docker 容器运行一个无限循环而不是原来的条目,你可以 exec bash 进入它,或者做任何你需要的。 完成后停止容器,删除/重命名您的自定义入口点。

答案 7 :(得分:0)

没有指定容器是否正在退出,只是您的代码崩溃了,您需要查看容器中发生了什么。如果它没有退出,这是另一个潜在的解决方案。

使用docker ps

获取容器ID

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