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

我想用一个不同的命令来启动一个停止的Docker容器,因为默认命令会崩溃——这意味着我不能启动容器,然后使用' Docker exec'。

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

幸运的是,我创建了带有-it选项的容器!

330899 次浏览

编辑这个文件(对应于你停止的容器):

vi /var/lib/docker/containers/923...4f6/config.json

改变“路径”;参数指向你的新命令,例如/bin/bash.你也可以设置&;Args"参数向命令传递参数。

重新启动docker服务(注意,这将停止所有正在运行的容器,除非你首先启用live-restore):

service docker restart

列出你的容器,并确保命令已经更改:

docker ps -a

启动容器并连接到它,您现在应该在您的shell中!

docker start -ai mad_brattain

使用Docker 1.7.1在Fedora 22上工作。

注意:如果你的shell不是交互式的(例如,你没有创建带有-it选项的原始容器),你可以将命令改为“;/bin/sleep 600"/bin/tail -f /dev/null"给你足够的时间来执行“docker exec -it CONTID /bin/bash"作为另一种获得壳的方式。

更新版本的docker有config.v2。json,在那里你需要改变入口点或Cmd(感谢user60561)。

找到停止的容器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

在Entrypoint脚本的顶部添加一个检查

Docker确实需要将其作为一个新特性来实现,但这里有另一个变通选项,用于你有一个在成功或失败后终止的Entrypoint,这可能会使调试变得困难。

如果您还没有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。我用我的入口点脚本运行容器,就像这样:

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脚本来重新运行它。

我把@Dmitriusan的回答变成了一个别名:

别名docker-run- prer -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别名,它将把你放入前一个容器中的壳中。

有助于调试失败的docker builds。

我的问题:

  • 我用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
  • 然后,您可以决定从中创建一个新映像

这并不是你所要求的,但是如果你只是想检查文件,你可以在一个停止的容器上使用docker export

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

我找到了一个简单的命令

docker start -a [container_name]

这样就可以了

docker start [container_name]

然后

docker exec -it [container_name] bash
对我来说,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(如果存在,请确保备份一个现有的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容器运行一个无限循环,而不是原来的入口,你可以对它执行bash,或者做任何你需要的事情。 当容器停止后,删除/重命名自定义入口点

在容器启动后,docker似乎不能更改入口点。但是您可以设置一个自定义入口点,并在下次重新启动入口点时更改入口点的代码。

例如,你像这样运行一个容器:

docker run --name c --entrypoint "/boot" -v "./boot":/boot $image

下面是引导入口点:

#!/bin/bash
command_a

当你需要用不同的命令重新启动c时,你只需要改变启动脚本:

#!/bin/bash
command_b

并重新启动:

docker restart c

我有一个docker容器,MariaDB容器在启动时不断崩溃,因为损坏了InnoDB表。

我解决问题的方法是:

  • 从容器中复制docker-entrypoint.sh到本地文件系统(docker cp)
  • 编辑它以包含所需的命令行参数(在我的例子中——innodb-force-recovery=1)
  • 将编辑过的文件复制回docker容器,覆盖现有的入口点脚本。

——entrypoint /bin/bash cont_id_or_name

(对于conven,把你的env, vol挂载在docker-compose.yml)

或者使用docker运行并手动指定所有参数

关于这个问题有很多讨论,所以我想再补充一个我没有立即看到上面列出的:

如果容器到入口点的完整路径是已知的(或通过检查可以发现),那么可以使用'docker cp'将其复制进或复制出停止的容器。这意味着您可以从容器中复制原始代码,编辑它的副本以启动bash shell(或长睡眠计时器),而不是它正在做的任何事情,然后重新启动容器。现在可以使用bash shell进一步编辑正在运行的容器以纠正任何问题。当编辑完成后,将原始入口点的另一个docker cp返回到容器中,重新启动应该可以做到这一点。

我曾经用它来纠正一个“快速修复”,我黄油手指,不再能够运行正常入口点的容器,直到它被纠正。

我也同意应该有一种更好的方式通过docker来做到这一点:也许可以选择“docker restart”来允许另一个入口点?嘿,也许这已经适用于“——entrypoint”?不确定,没有尝试过,留给读者练习,如果有用请告诉我。:)

大多数情况下,人们在修改配置文件时会遇到这种情况,我就是这样做的。我试图通过Vue SPA作为入口点绕过PHP/Apache服务器的CORS。不管怎样,如果你知道你要的文件,对我来说一个简单的解决办法是

  1. 复制你从图片中取出的文件:

    Docker cp bt-php:/etc/apache2/apache2.conf。

  2. 局部修复

  3. 复制回来

    Docker cp apache2.conf bt-php:/etc/apache2 .conf

  4. 重新启动容器

  5. *加分-由于这个文件正在被修改,将其添加到您的撰写或构建脚本,这样当您做对了,它将被烘焙到图像中!