如何在已经存在的Docker容器上运行命令?

我用-d创建了一个容器,所以它不是交互式的。

docker run -d shykes/pybuilder bin/bash

我看到容器已经退出:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

现在我想偶尔在机器上运行一些命令,然后退出。只是为了得到回应。

我试着启动机器。我试着连接。我认为我可以用容器调用run,但这似乎是不允许的。使用start似乎只是运行,然后很快就存在了。

退出后,我想回到交互模式。

我试着:

docker attach d6c45e8cc5f0

但我明白:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

但如果我启动它,它还是会退出。赶上22。我赢不了。

663155 次浏览

假设映像使用默认的入口点/bin/sh -c,那么运行/bin/bash将立即以守护模式(-d)退出。如果您希望这个容器运行交互式shell,请使用-it而不是-d。如果您想在容器中执行任意命令,通常是执行另一个进程,您可能想尝试nsenternsinit。看看https://blog.codecentric.de/en/2014/07/enter-docker-container/的细节。

您的容器将退出,因为您给它的命令将结束。使用以下选项来保持它的活性:

  • 保持STDIN打开,即使没有附加。
  • 分配一个伪tty。

所以你的新run命令是:

docker run -it -d shykes/pybuilder bin/bash

如果你想附加到一个已经运行的容器:

docker exec -it CONTAINER_ID /bin/bash

在这些示例中,使用/bin/bash作为命令。

2014年10月Docker团队介绍了docker exec命令: https://docs.docker.com/engine/reference/commandline/exec/

所以现在你可以在一个运行的容器中运行任何命令,只需要知道它的ID(或名称):

docker exec -it <container_id_or_name> echo "Hello from container!"

注意,exec命令只适用于已经运行的容器。如果容器当前处于停止状态,则需要先运行以下命令:

docker run -it -d shykes/pybuilder /bin/bash

这里最重要的是-d选项,它代表detached。这意味着您最初提供给容器的命令(/bin/bash)将在后台运行,而容器不会运行立即停止

这里的一些答案具有误导性,因为它们涉及正在运行的容器,而不是停止的容器。

Sven Dowideit在Docker论坛上解释说,容器被绑定到它们的进程上(Docker不能改变一个停止的容器的进程,似乎至少是由于它的内部结构:https://github.com/docker/docker/issues/1437)。所以,基本上唯一的选择就是用不同的命令commit容器到一个图像,run容器到一个图像。

参见https://forums.docker.com/t/run-command-in-stopped-container/343
(我相信“带参数的ENTRYPOINT”方法也不会起作用,因为你仍然无法将参数更改为一个停止的容器。

为了扩展katrmr的答案,如果容器由于错误而停止并且无法启动,您需要将它commit到一个图像。然后你可以在新镜像中启动bash:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image

这是我用上面的CDR LDN答案和我找到的答案在这里组合出来的答案。

下面的例子从一个镜像启动一个Arch Linux容器,然后使用pacman工具在该容器上安装git:

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

仅此而已。

我必须使用bash -c来运行我的命令: # EYZ0 < / p >

创建一个容器并向其发送命令,一个接一个:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command

不幸的是,用带有docker run --entrypoint的参数覆盖ENTRYPOINT来实现这个目标是不可能的。

注意:您可以使用——ENTRYPOINT覆盖ENTRYPOINT设置,但是 这只能将二进制文件设置为exec(不会使用sh -c)

简单的回答是:同时启动和附加。在这种情况下,你所做的正是你所要求的。

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME>

确保更改<CONTAINER_ID/CONTAINER_NAME>

所以我认为答案比上面许多误导性的答案更简单。

启动已停止的现有容器

docker start <container-name/ID>

停止正在运行的容器

docker stop <container-name/ID>

然后登录到容器的交互式shell

docker exec -it <container-name/ID> bash

在一个命令中启动一个现有容器并附加到它

docker start -ai <container-name/ID>

注意,这将在退出时停止容器。但通常情况下,您需要启动容器,在完成后附加并停止它。

docker exec bash标准输入管道命令

必须删除-t才能工作:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

有时这比使用CLI选项更方便。

测试:

sudo docker run --name ub16 -it ubuntu:16.04 bash

然后在另一个壳上:

echo 'touch myfile' | sudo docker exec -i ub16 bash

然后在第一能层

ls -l myfile

在Docker 1.13.1, Ubuntu 16.04主机上测试。

Mac:

$ docker exec -it <container-name> sh

如果您想以root用户连接:

$ docker exec -u 0 -it <container-name> sh

如果您试图运行shell脚本,则需要以bash方式运行它。

docker exec -it containerid bash -c /path/to/your/script.sh
# docker exec -d container_id command

例:

# docker exec -d xcdefrdtt service jira stop

我正在运行windows容器,我需要在docker容器中查看创建和复制的文件和文件夹。

为了做到这一点,我使用下面的docker entrypoint命令来获得在容器内运行或附加到容器的命令提示符。

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

这帮助我将命令提示符附加到容器,并使容器保持活动状态。:)

一个快速恢复和访问最近退出的容器的方法:

docker start -a -i `docker ps -q -l`

我想指出,上面的答案有点误导人。

执行docker run的问题是每次都会创建一个新容器。然而,在某些情况下,我们希望重新访问旧容器或不占用新容器的空间。

(给定clever_bardeen是创建的容器的名称…)

在OP的情况下,通过执行以下命令确保docker映像首先运行:

docker start clever_bardeen

然后,使用以下命令执行docker容器:

docker exec -it clever_bardeen /bin/bash

我通常用这个:

    docker exec -it my-container-name bash

与正在运行的容器持续交互。

一个简单的解决方案为我解决了类似的问题:

docker run --interactive --tty <name_of_image>