15

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

我有两个容器。

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

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

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

有什么建议么?

4

5 回答 5

9

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

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

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

  1. 在你的容器上安装 ssh 并通过 ssh 执行命令
  2. 共享一个卷并有一个过程来监视触发您的批处理的东西
于 2019-11-25T16:19:44.403 回答
8

你有几个选择,但首先想到的两个是:

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

我能想到的大多数其他想法只是选项 (2) 的变体,将 SSHD 替换为其他工具。

另请注意,Docker 网络有点奇怪(至少在 Mac 主机上),因此您需要确保容器使用相同的 docker-network 并且能够通过它进行通信。

编辑添加:
要完全清楚,不要在实验室或非常受控的开发环境之外使用选项 1。它采用对主机上的 Docker 运行时具有完全权限的安全套接字,并授予从容器对它的未经检查的访问权限。这样做可以很容易地突破 Docker 沙箱并破坏主机系统。我认为唯一可以接受的地方是作为全栈集成测试设置的一部分,该设置只能由开发人员临时运行。这是一种技巧,在某些非常特殊的情况下可能是一种有用的捷径,但其缺点不能被夸大。

于 2019-11-25T16:19:58.153 回答
7

我专门为这个用例编写了一个 python 包。

Flask-Shell2HTTP是一个 Flask 扩展,只需 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 微服务,这些微服务可以异步执行带有动态参数的预定义 shell 命令/脚本并获取结果。

它支持文件上传、回调 fn、反应式编程等。我建议您查看示例

于 2020-09-01T15:08:16.270 回答
0

之前在这里提到过,但一个合理的半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 自动输入密码,或者您可以使用一些更 hacky 的sshpass方法(首先使用 安装它sudo apt install sshpass):

sshpass -p 'foobob' ssh foobob@<container-id>
于 2020-07-17T20:52:09.190 回答
-2

我相信

docker exec -it <container_name> <command>

应该可以工作,即使在容器内。

您还可以尝试挂载到docker.sock您尝试从以下位置执行命令的容器中:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...
于 2019-11-25T16:06:05.267 回答