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

aaa*_*210 212 docker

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

基本上我想启动一个shell,以便我可以检查容器的内容.

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

Dmi*_*san 323

找到已停止的容器ID

docker ps -a
Run Code Online (Sandbox Code Playgroud)

提交已停止的容器:

此命令将修改后的容器状态保存到新映像中 user/test_image

docker commit $CONTAINER_ID user/test_image
Run Code Online (Sandbox Code Playgroud)

使用不同的入口点开始/运行:

docker run -ti --entrypoint=sh user/test_image
Run Code Online (Sandbox Code Playgroud)

入口点参数描述:https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

注意:

上面的步骤只是启动具有相同文件系统状态的已停止容器.这对于快速调查非常有用.但是环境变量,网络配置,附加卷和其他人员不是继承的,您应该明确指定所有这些参数.

从这里借用了启动已停止容器的步骤:(最后评论)https://github.com/docker/docker/issues/18078

  • 如果能以某种方式获得相同的环境,网络配置和附加的卷,那将是很棒的。是否可以将“检查”输出转换为用于后续运行的配置? (4认同)
  • 这几乎没有关于env,卷,UID的所有配置......它与已停止的容器有共同之处的是文件系统(这对某些人来说可能已经够了) (3认同)
  • 不,图像是只读的。它将修改后的容器状态保存到新图像 test_image 中 (2认同)
  • @Webman,是的,但对于在停止容器之前安装的卷而言,情况并非如此。下次启动容器时,您必须明确附加相同的卷 (2认同)
  • @EmreTapcı,我认为这样做违反了 Docker 意识形态。与虚拟机相比,容器旨在成为一个一次性使用的运行即丢弃的实体。您可以尝试遵循 *aaa90210* 答案,但这将是一种黑客行为。 (2认同)

aaa*_*210 118

编辑此文件(对应于已停止的容器):

vi /var/lib/docker/containers/923...4f6/config.json
Run Code Online (Sandbox Code Playgroud)

更改"Path"参数以指向新命令,例如/ bin/bash.您还可以设置"Args"参数以将参数传递给命令.

重启docker服务(注意这将停止所有正在运行的容器):

service docker restart
Run Code Online (Sandbox Code Playgroud)

列出容器并确保命令已更改:

docker ps -a
Run Code Online (Sandbox Code Playgroud)

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

docker start -ai mad_brattain
Run Code Online (Sandbox Code Playgroud)

使用Docker 1.7.1在Fedora 22上工作.

注意:如果您的shell不是交互式的(例如,您没有使用-it选项创建原始容器),则可以将命令更改为"/ bin/sleep 600"或"/ bin/tail -f/dev/null"给你足够的时间做"docker exec -it CONTID/bin/bash"作为获取shell的另一种方式.

注意2:较新版本的docker有config.v2.json,您需要更改Entrypoint或Cmd(感谢user60561).

  • 我的眼睛.我的眼睛.我希望这是一个功能请求,可以在Docker中正确处理这个问题. (38认同)
  • 重新启动容器配置文件后始终返回到以前的版本。 (7认同)
  • 对于 Windows 上的 Docker Desktop,您可以在以下位置找到“config.v2.json”文件:“\\wsl$\docker-desktop-data\version-pack-data\community\docker\containers\CONTAINER_ID\config.v2”。 json` (5认同)
  • 较新版本的docker具有`config.v2.json`,您需要在其中更改`Entrypoint`或`Cmd`。 (4认同)
  • 对于这个问题,这是唯一真正准确的答案:所有其他命题运行一个"几乎相同"的容器,但是他们忘记了卷,环境,UID,... (3认同)
  • 在我的情况下/ usr/bin/sleep不可用.我成功地使用了`..."Path":"tail","Args":[" - f","/ dev/null"] ...... (3认同)
  • @AlexeyStrakh您可以尝试运行"/ usr/bin/sleep 600",然后执行"docker exec -it/bin/bash"来获取shell.虽然我不确定如何在Path变量上放置参数.否则,尝试找到另一个命令,它将保持足够长的时间让你做一个exec,或者看看Dmitriusan的回答. (2认同)
  • 还有另一个名为"Arguments"的属性来传递参数.虽然我发现另一个解决方案是`docker cp`从已停止的容器中复制所需的文件,但更新配置并将其放回原处. (2认同)

Eth*_*n T 16

将检查添加到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
Run Code Online (Sandbox Code Playgroud)

为确保cat保持连接,您可能需要提供TTY.我正在使用我的Entrypoint脚本运行容器,如下所示:

docker run -t --entrypoint entrypoint.sh image_name
Run Code Online (Sandbox Code Playgroud)

这将导致脚本运行一次,创建一个指示它已经运行的文件(在容器的虚拟文件系统中).然后,您可以重新启动容器以执行调试:

docker start container_name
Run Code Online (Sandbox Code Playgroud)

当您重新启动容器时,already_ran将找到该文件,导致Entrypoint脚本停止cat(它只是永远等待永远不会出现的输入,但保持容器处于活动状态).然后,您可以执行调试bash会话:

docker exec -i container_name bash
Run Code Online (Sandbox Code Playgroud)

当容器正在运行时,如果需要以这种方式进行调试,还可以删除already_ran并手动执行entrypoint.sh脚本以重新运行它.

  • 另外,你可以让入口点运行`/ bin/sh`而不是`cat` - 然后你可以随时进入重启状态.你的解决方案摇滚 (3认同)

小智 9

docker-compose run --entrypoint /bin/bash cont_id_or_name

(对于 conven,请将您的 env、vol 安装在 docker-compose.yml 中)

或使用 docker run 并手动指定所有参数


Lar*_*sen 6

这并不完全是您所要求的,但docker export如果您只想检查文件,则可以在已停止的容器上使用。

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
Run Code Online (Sandbox Code Playgroud)


Dea*_*her 5

我采用了@Dmitriusan 的答案并将其设为别名:

别名 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