如何从一个 docker 容器执行命令到另一个容器

How to execute command from one docker container to another

我正在创建一个应用程序,允许用户上传视频文件,然后这些文件将经过一些处理。

我有两个容器。

  1. Nginx 为用户上传视频文件的网站提供服务的容器。
  2. 安装了 FFmpeg 和一些其他处理工具的视频处理容器。

我想达到的目标。我需要容器 1 才能 运行 容器 2 上的 bash 脚本。

据我所知,一种可能性是让它们通过 API 通过 HTTP 进行通信。但是然后我需要在容器 2 中安装一个 Web 服务器并编写一个 API ,这似乎有点过分了。 我只想执行一个 bash 脚本。

有什么建议吗?

我相信

docker exec -it <container_name> <command>

应该可以工作,即使在容器内也是如此。

您也可以尝试在您尝试从以下命令执行命令的容器中挂载到 docker.sock

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

运行 来自容器的 docker 命令并不简单,也不是一个好主意(在我看来),因为:

  1. 您需要在容器上安装 docker(并在 docker 中执行 docker)
  2. 您需要共享 unix 套接字,如果您不知道自己在做什么,这不是一件好事。

所以,这给我们留下了两个解决方案:

  1. 在你的容器上安装 ssh 并通过 ssh 执行命令
  2. 共享一个卷并有一个进程来监视触发你的批处理的东西

您有几个选择,但您想到的前两个是:

  1. 在容器 1 中,安装 Docker CLI 并绑定挂载 /var/run/docker.sock(您需要从 启动容器时托管)。然后,在容器内,你 应该能够对绑定安装使用 docker 命令 套接字就好像你从主机上执行它们一样(你也可以 需要chmod容器内的socket允许非root 用户执行此操作。
  2. 您可以在容器 2 上安装 SSHD,然后从容器 1 中安装 ssh 和 运行 您的脚本。这里的优点是您不需要在容器内部进行任何更改来说明它们 运行ning in Docker 而不是裸机这一事实。缺点是您需要将 SSHD 设置添加到 Docker 文件或启动脚本中。

我能想到的大多数其他想法只是选项 (2) 的变体,SSHD 被其他工具取代。

还要注意 Docker 网络有点奇怪(至少在 Mac 主机上),所以你需要确保容器使用相同的 docker-网络并能够通过它进行通信。

警告:

完全清楚,不要在实验室或非常受控的开发环境之外使用选项 1。它正在使用一个安全套接字,该套接字对 主机 上的 Docker 运行 时间具有完全权限,并授予从 对其进行未经检查的访问权限集装箱。这样做可以轻而易举地突破 Docker 沙箱并危害主机系统。我认为唯一可以接受的地方是作为全栈集成测试设置的一部分,它只会由开发人员 运行 临时设置。在某些非常特殊的情况下,这是一个有用的捷径,但缺点怎么强调都不为过。

之前在这里提到过,但一个合理的、半hacky的选择是在两个容器中安装SSH,然后使用ssh在另一个容器上执行命令:

# install SSH, if you don't have it already
sudo apt install openssh-server

# start the ssh service
sudo service start ssh

# start the daemon
sudo /usr/sbin/sshd -D &

假设你不想一直是 root,你可以添加默认用户(在本例中,'foobob'):

useradd -m --no-log-init --system  --uid 1000 foobob -s /bin/bash -g sudo -G root

#change password
echo 'foobob:foobob' | chpasswd

在源容器和目标容器上执行此操作。现在您可以执行从 container_1 到 container_2 的命令。

# obtain container-id of target container using 'docker ps'
ssh foobob@<container-id> << "EOL"
echo 'hello bob from container 1' > message.txt
EOL

您可以使用 ssh-agent 自动设置密码,或者您可以使用 sshpass 的一些技巧(首先使用 sudo apt install sshpass 安装):

sshpass -p 'foobob' ssh foobob@<container-id>

我专门为此写了一个 python 包 use-case。

Flask-Shell2HTTP 是一个 Flask-extension,只需 5 行代码即可将命令行工具转换为 RESTful API。

示例代码:

from flask import Flask
from flask_executor import Executor
from flask_shell2http import Shell2HTTP

app = Flask(__name__)
executor = Executor(app)
shell2http = Shell2HTTP(app=app, executor=executor, base_url_prefix="/commands/")

shell2http.register_command(endpoint="saythis", command_name="echo")
shell2http.register_command(endpoint="run", command_name="./myscript")

可以随便叫,

$ curl -X POST -H 'Content-Type: application/json' -d '{"args": ["Hello", "World!"]}' http://localhost:4000/commands/saythis

您可以使用它来创建 RESTful micro-services,它可以使用动态参数异步执行 pre-defined shell commands/scripts 并获取结果。

支持文件上传、回调fn、响应式编程等。我建议您查看 Examples.