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

Мы начали использовать контейнеры при создании инструментов и утилит, поэтому отдельным разработчикам не нужно беспокоиться об установке необходимых компонентов. Отлично работает, например:

docker run --rm -v $PWD/input.yaml:/input.yaml  our.registry.com/dev/toolA /input.yaml

Пока toolA не потребуется вызвать другую утилиту, toolB, которая также заключена в контейнер.

Есть ли общий способ запустить контейнер изнутри контейнера, чтобы он работал с docker, podman или чем-то еще, что есть в container-tech-du-jour, без того, чтобы вызывающий toolA добавлял страшные дополнительные параметры, такие как, например, --privileged=true или -v /var/run/docker.sock:/var/run/docker.sock?

Я знаю, что можно запустить docker-in-docker, и, по-видимому, можно также запустить podman-in-podman, но это не рекомендуется. Добавление -v /var/run/docker.sock:/var/run/docker.sock - это рекомендуемый подход, но это только для докеров, верно?

Потому что в противном случае это ненадежная абстракция. В настоящее время я создаю toolA, включая основные части контейнера toolB в toolA, делая toolA чувствительным к изменениям в реализации toolB, которых я бы хотел избежать. Или я мог бы собрать toolA, но поддерживать только докер и требовать от пользователей добавления параметра -v /var/run/docker.sock:/var/run/docker.sock :-(.

Есть ли более элегантный способ вызова контейнера toolBs из контейнера toolA, который работает со всеми распространенными технологиями контейнеров и не требует дополнительных параметров при запуске toolA?


person Peter V. Mørch    schedule 04.03.2021    source источник


Ответы (3)


Есть ли общий способ запустить контейнер из контейнера [...] без добавления пугающих дополнительных параметров, таких как [...] -v /var/run/docker.sock:/var/run/docker.sock ?

No.

(Вам необходимо смонтировать Docker-сокет хоста; вызывающий контейнер не должен быть --privileged; вы не можете ограничить то, что вызывающий контейнер может делать, когда у него есть доступ к сокету, поэтому он может сам запускать привилегированные контейнеры или запускать контейнер bind-монтирование /etc каталога хоста или иным образом делать непослушные вещи. Я не совсем уверен, как это взаимодействует с Podman.)

Особенно, если контейнеру необходимо выполнить обратную запись в хост-систему, трудно сделать команду docker run удобной компактной. Вам понадобится параметр -u, чтобы указать идентификатор пользователя хоста, параметры -v для сокета Docker и текущего каталога, --rm, а также имя репозитория, все как накладные расходы, каждый раз, когда вы запускаете команду. Я мог бы предпочесть использовать собственную команду, возможно, на широко доступном языке сценариев, таком как Python или оболочка Bourne.

Если вы все еще хотите запустить это из контейнера, вы можете COPY или иным образом установить инструмент B в тот же контейнер, чтобы вы могли выполнить обычный вызов подпроцесса для его запуска; или разбейте инструмент B на библиотеку и приложение и включите библиотеку в инструмент A (вроде того, что вы делаете сейчас, но более формализовано).

person David Maze    schedule 04.03.2021
comment
Хорошо, теперь я знаю точно. Я ожидал, что смогу запустить (под) контейнер, выставляя только то, к чему у контейнера есть доступ, и ничего больше. Кажется, я не могу. То, что я делаю в настоящее время, - это именно то, что вы предлагаете КОПИРОВАТЬ соответствующие фрагменты из toolB в образ, который я создаю для toolA. Но это отстой, когда у меня есть toolB в качестве контейнера докеров, созданный кем-то другим. - person Peter V. Mørch; 04.03.2021
comment
В чем проблема с контейнером? У вас есть Dockerfile контейнера toolB? - person jordanvrtanoski; 04.03.2021
comment
Моя проблема связана с инкапсуляцией. Команда, стоящая за toolB, раскрывает интерфейс контейнера докеров. Из-за того, что возились с внутренними компонентами контейнера toolB, A) я не использую опубликованный интерфейс и B) вызов toolB становится намного более громоздким. Это немного похоже на вызов частных интерфейсов или методов с использованием рефлексии или подобного хакерского подхода. Конечно, он уже работает, извлекая toolB из своего контейнера, но это хак. - person Peter V. Mørch; 04.03.2021

Подход к запуску контейнера изнутри контейнера необычен, и его можно избежать, изменив структуру потока. Это будет работать, но создаст огромную сложность и накладные расходы.

Если вам нужен инструмент только на период во время сборки, вы можете использовать многоэтапные сборки. Что вам нужно сделать, так это создать базовый контейнер, обычно называемый builder, в котором есть все инструменты, необходимые для сборки, получить проект в базовом контейнере и запустить сборку. После завершения сборки вы перейдете к следующему этапу и создадите базовый бегун, в котором вы установите только необходимые библиотеки и модули для среды выполнения и добавите полученные файлы из builder в контейнер бегуна.

Таким образом, вы получите полный контроль над средами build-time и run-time. Кроме того, если у вас несколько проектов или сложных сборок, вы можете использовать многоступенчатую сборку в сочетании с buildx для параллельного запуска сборки.

person jordanvrtanoski    schedule 04.03.2021
comment
К сожалению, toolB нужен во время выполнения, а не во время сборки. А toolB создан кем-то другим. Я использую многоступенчатую сборку и копирую toolB из контейнера для toolB. - person Peter V. Mørch; 04.03.2021

Передача -v /var/run/docker.sock:/var/run/docker.sock внешнему контейнеру проблематична с точки зрения безопасности, поскольку это дает внешнему контейнеру разрешение запускать контейнеры на хосте. Вредоносный внешний контейнер может запускать такие контейнеры с привязкой, чтобы можно было записывать каталоги хоста.

Запуск внешнего контейнера с Podman от имени обычного пользователя (без root) с --privileged защищает вас от этого сценария. Внешний контейнер сможет записывать только в каталоги, которые вы передаете как привязку-монтирование (например, с параметром командной строки -v).

Значение флага --privileged объясняется в этой статье Red Hat.

Обновление от июня 2021 г.. Больше нет необходимости передавать флаг --privileged при запуске Podman в Podman. См. Мой пример в https://stackoverflow.com/a/64537135/757777 и в сообщении блога Red Hat Как использовать Podman внутри контейнера

person Erik Sjölund    schedule 04.03.2021
comment
Да, поэтому запускать докер в докере не рекомендуется, -v /var/run/docker.sock:/var/run/docker.sock во внешний контейнер вроде как более рекомендуется, но проблематично с точки зрения безопасности, а podman с --privilege вроде как лучше, за исключением того, что на самом деле никто не использует podman (соотношение использования докера / подмана составляет 72: 1 согласно тенденциям Google). :-( Это еще незрелая техника ... - person Peter V. Mørch; 05.03.2021