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

Joh*_*ton 447 docker

我创建了一个容器,-d因此它不是交互式的.

docker run -d shykes/pybuilder bin/bash
Run Code Online (Sandbox Code Playgroud)

我看到容器已退出:

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 Code Online (Sandbox Code Playgroud)

现在我想在机器上运行偶尔的命令并退出.只是为了得到答复.

我试着启动机器.我试着附上.我以为我可以run用容器打电话,但似乎不允许这样做.使用start似乎只是运行然后快速存在.

退出后我想回到交互模式.

我试过了:

docker attach d6c45e8cc5f0
Run Code Online (Sandbox Code Playgroud)

但我得到:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first
Run Code Online (Sandbox Code Playgroud)

但是,如果我开始它,它无论如何都会退出.抓住22.我无法获胜.

Sca*_*dge 512

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!"
Run Code Online (Sandbox Code Playgroud)

请注意,该exec命令仅适用于已在运行的容器.如果容器当前已停止,则需要先使用以下命令运行它:

docker run -it -d shykes/pybuilder /bin/bash
Run Code Online (Sandbox Code Playgroud)

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

  • 这不适用于已停止的容器,只能运行正在运行的容器.因此,如果你有一个立即停止自己的容器,就像在问题中一样,这实际上不会在其中运行其他东西. (118认同)
  • @ Jan-PhilipGehrcke顺便说一句,这个人的用户名已从`CDR LDN`更改为`cdrev`以获得以下答案(http://stackoverflow.com/a/26181666/149428). (5认同)
  • @interfect是对的,CDR LDN有更全面的答案. (4认同)
  • omg为什么这么复杂?似乎是你需要做的最基本的事情.我们不能按照他们的意图使用它. (4认同)
  • 为什么要通过`-it`? (3认同)
  • “docker run -it -d shykes/pybuilder /bin/bash”创建了另一个容器实例 (3认同)
  • 因此,这个高级问题与我正在寻求“如何在现有的 docker 容器上运行命令?”的答案相同。这个解决方案正是我正在寻找的解决方案。我不需要添加 `-it` 来在 docker 容器中运行命令。我理解上下文的混乱,但这是我针对该确切问题所需的解决方案。不确定这对于“正确”答案意味着什么,也许应该更改标题?不管怎样,这都会得到我的支持。 (2认同)

cdr*_*rev 281

您的容器将退出,因为您提供的命令将结束.使用以下选项使其保持活动状态:

  • -i 即使没有连接,也要保持STDIN打开.
  • -t 分配伪TTY.

所以你的新run命令是:

docker run -it -d shykes/pybuilder bin/bash
Run Code Online (Sandbox Code Playgroud)

如果您想要附加到已经运行的容器:

docker exec -it CONTAINER_ID /bin/bash
Run Code Online (Sandbox Code Playgroud)

在这些示例/bin/bash中用作命令.

  • 尝试了docker exec -it CONTAINER_ID / bin / bash -c“ export VAR = 1 &amp;&amp; echo $ VAR”,并打印了空变量(预期为1)。我想念什么? (2认同)

Pet*_* T. 103

所以我认为答案很简单,而不是上面的许多误导性答案.

启动已停止的现有容器

docker start <container-name/ID>
Run Code Online (Sandbox Code Playgroud)

停止正在运行的容器

docker stop <container-name/ID>
Run Code Online (Sandbox Code Playgroud)

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

docker exec -it <container-name/ID> bash
Run Code Online (Sandbox Code Playgroud)

  • @Peter T.实际上,我发现你的答案比其他人提供的答案简洁得多.我不明白为什么人们更喜欢复杂化一个非常简单的问题.谢谢彼得这个答案. (7认同)
  • 我执行“docker start -ai &lt;ID&gt;”,它立即停止。所以我无法进入 insede 容器。应如何创建容器才能允许进入? (6认同)
  • 这要求当你创建 docker 时,你使用 -it /sf/ask/3165162871/ 否则它不会启动..所以你会做 docker start &lt;container-id&gt; 然后 docker ps -l 你会看到它在启动后没有启动。然后附加将失败。所以也必须用 -it 创建。 (2认同)

Aar*_*n V 89

要扩展katrmr的答案,如果容器因为错误而停止并且无法启动,则需要将commit其映射到图像.然后你可以在新图像中启动bash:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image
Run Code Online (Sandbox Code Playgroud)


kat*_*rmr 40

这里的一些答案具有误导性,因为它们涉及正在运行但未停止的容器.

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带参数"方法也不起作用,因为您仍然无法更改停止容器的参数.)

  • 注意:运行没有`-it`的`bin/bash`不会改变容器中的任何内容,因此提交它并不是必需的,CDR LDN会为OP的特定情况提供正确的答案.仍然,`commit`是如何改变容器过程的技术问题的答案. (2认同)

vel*_*lop 20

我不得不使用bash -c来运行我的命令: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"


lan*_*.io 17

创建一个容器并逐个发送命令:

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
Run Code Online (Sandbox Code Playgroud)


Jos*_*ren 8

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

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

(给出的clever_bardeen是创建的容器的名称......)

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

docker start clever_bardeen
Run Code Online (Sandbox Code Playgroud)

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

docker exec -it clever_bardeen /bin/bash
Run Code Online (Sandbox Code Playgroud)


imr*_*iss 7

这是我使用上面的CDR LDN答案和我在这里找到的答案组成的综合答案.

以下示例从映像启动Arch Linux容器,然后git使用该pacman工具在该容器上安装:

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"
Run Code Online (Sandbox Code Playgroud)

就这些.


MrK*_*lli 7

如果您尝试运行 shell 脚本,则需要将其作为 bash 运行。

docker exec -it containerid bash -c /path/to/your/script.sh
Run Code Online (Sandbox Code Playgroud)


Cir*_*四事件 5

管道命令到标准输入

必须删除-t它才能工作:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash
Run Code Online (Sandbox Code Playgroud)

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

测试:

sudo docker run --name ub16 -it ubuntu:16.04 bash
Run Code Online (Sandbox Code Playgroud)

然后在另一个外壳上:

echo 'touch myfile' | sudo docker exec -i ub16 bash
Run Code Online (Sandbox Code Playgroud)

然后在第一个外壳上:

ls -l myfile
Run Code Online (Sandbox Code Playgroud)

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


Ami*_*aei 5

我通常用这个:

    docker exec -it my-container-name bash
Run Code Online (Sandbox Code Playgroud)

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

  • 重点是,您无法在已退出的容器上运行此命令。它显示以下错误:来自守护程序的错误响应:容器 31ed0... 未运行 (7认同)
  • 您确定当您运行此命令时您的容器尚未处于运行状态吗? (2认同)