Как выполнить команду из одного контейнера докеров в другой

Я создаю приложение, которое позволит пользователям загружать видеофайлы, которые затем будут подвергнуты некоторой обработке.

У меня есть два контейнера.

  1. Nginx контейнер, обслуживающий веб-сайт, куда пользователи могут загружать свои видеофайлы.
  2. Контейнер обработки видео с FFmpeg и еще кое-что для обработки.

Чего я хочу добиться. Мне нужен контейнер 1, чтобы иметь возможность запускать сценарий bash в контейнере 2.

Насколько я понимаю, одна из возможностей - заставить их общаться через HTTP через API. Но тогда мне нужно было бы установить веб-сервер в контейнер 2 и написать API, который кажется немного излишним. Я просто хочу выполнить сценарий bash.

Какие-либо предложения?

5 ответов

Решение

У вас есть несколько вариантов, но первые два, которые приходят в голову, это:

  1. В контейнере 1 установите Docker CLI и привяжите mount/var/run/docker.sock(вам нужно указать монтирование привязки с хоста при запуске контейнера). Затем внутри контейнера вы сможете использоватьdocker команды для подключенного сокета, как если бы вы выполняли их с хоста (вам также может потребоваться chmod сокет внутри контейнера, чтобы позволить это сделать пользователю без полномочий root.
  2. Вы можете установить SSHD на контейнере 2, а затем sshиз контейнера 1 и запустите свой скрипт. Преимущество здесь в том, что вам не нужно вносить какие-либо изменения внутри контейнеров, чтобы учесть тот факт, что они работают в Docker, а не на голом железе. Обратной стороной является то, что вам нужно будет добавить настройку SSHD в свой Dockerfile или в сценарии запуска.

Большинство других идей, которые я могу придумать, - это просто варианты варианта (2) с заменой SSHD каким-либо другим инструментом.

Также имейте в виду, что сеть Docker немного странная (по крайней мере, на хостах Mac), поэтому вам нужно убедиться, что контейнеры используют одну и ту же сеть докеров и могут обмениваться данными по ней.

Я написал пакет python специально для этого варианта использования.

Flask-Shell2HTTP - это расширение Flask для преобразования инструмента командной строки в RESTful API с помощью всего 5 строк кода.

Пример кода:

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, которые могут асинхронно выполнять предварительно определенные команды / сценарии оболочки с динамическими аргументами и получать результат.

Он поддерживает загрузку файлов, обратный вызов fn, реактивное программирование и многое другое. Я рекомендую вам ознакомиться с примерами.

Запуск docker команда из контейнера непростая и не очень хорошая идея (на мой взгляд), потому что:

  1. Вам нужно будет установить докер в контейнер (и сделать докер в докере)
  2. Вам нужно будет совместно использовать сокет unix, что не очень хорошо, если вы не знаете, что делаете.

Итак, остается два решения:

  1. Установите ssh на свой контейнер и выполните команду через ssh
  2. Поделитесь томом и получите процесс, который будет следить за тем, чтобы что-то запустило вашу партию

Об этом упоминалось здесь ранее, но разумный, полувакансный вариант - установить 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

Сделайте это как для исходного, так и для целевого контейнеров. Теперь вы можете выполнить команду из контейнера_1 в контейнер_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>

Я верю

docker exec -it <container_name> <command>

должно работать даже внутри контейнера.

Вы также можете попытаться смонтировать docker.sock в контейнере вы пытаетесь выполнить команду из:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...
Другие вопросы по тегам