Предположим, я создаю микросервис, который изменяет размер и оптимизирует файлы изображений. Это давно работающий демон, который предоставляет HTTP API, отвечающий стандартным требованиям. GET
/POST
ответы. Исходя из моих знаний о Docker, это идеальный вариант использования для контейнеризации - один процесс (демон HTTP-сервера) работает бесконечно в выделенном контейнере.
Для меня все становится непонятным, если мы на один уровень глубже заглянем в возможный способ построения этой службы. Предположим, что для каждого поступающего запроса служба запускает процесс ImageMagick для изменения размера изображения, а затем другой pngquant или аналогичный процесс для уменьшения размера файла. Поскольку эти программы будут обрабатывать потенциально ненадежные данные изображений, предоставленные пользователем, важно иметь возможность обновлять каждый компонент до последней доступной версии, как только эти новые версии будут выпущены. Но как мне разделить эти компоненты на образы и контейнеры Docker?
Я придумал несколько разных подходов, но мне все равно кажется, что я чего-то упускаю:
1. Один большой контейнер. При создании контейнера HTTP API установите / скомпилируйте утилиты ImageMagick / pngquant одновременно. Насколько известно демону API, он работает как на любом другом компьютере. Чтобы обновить один из двоичных файлов, перестройте весь контейнер (даже если сам API-демон не изменился). Если необходимо протестировать / разработать против ImageMagick независимо, это может быть неудобно, потому что это не является целью макета этого контейнера.
2. Контейнеры с контейнерами. HTTP API - это собственный контейнер, ImageMagick - это собственный контейнер, pngquant - это собственный контейнер и так далее. Когда API обрабатывает запрос, требующий вызова одной из этих утилит, код API запускает контейнер для преобразования одного файла изображения, и этот контейнер уничтожается после завершения преобразования. Насколько я понимаю, коду HTTP API потребуются довольно высокие разрешения, чтобы иметь возможность создавать новый контейнер; может быть неразумным подходом с точки зрения безопасности.
3. Обертки и клей. Оберните ImageMagick и pngquant в пользовательский долго работающий код демона, чтобы эти контейнеры никогда не выходили. Попросите контейнер HTTP API обмениваться данными с другими по сети Docker по мере необходимости. Похоже, много бессмысленных косвенных указаний и сложности без реальной выгоды.
4. Что-то в композиции изображения, которое мне не хватает. Не похоже, что существует чистый способ «кусочно» собрать контейнер из нескольких независимо заменяемых изображений. Было бы интересно, если бы существовал способ объединить несколько изображений, каждое из которых содержит одно из ImageMagick, pngquant и HTTP API, в один контейнер. Основываясь на том, что я видел, замена / изменение изображения также изменяет все изображения, которые были созданы на его основе, делая этот подход не так уж и отличным от №1.
Что я действительно ищу, прежде всего, так это возможность независимо разрабатывать / строить / тестировать / развертывать компоненты программного стека контейнера без перекомпоновки или переустановки частей, которые не изменились. Если это слишком сильно противоречит философии дизайна Docker, я бы хотел либо изменить свой взгляд на подход, либо поискать другие инструменты.
Просто спроектируйте это с помощью нескольких «независимых» контейнеров, некоторые из которых зависят от других через удаленный API.
Нет необходимости иметь «контейнеры запускают контейнеры». У вас просто есть контейнер, принимающий запросы для обработки с помощью ImageMagick, и он просто ожидает непрерывной обработки запросов. Если вам нужно обновить этот контейнер отдельно, сделайте это. Этот непрерывный процесс похож на вашу точку «обертки и клея».
Обратите внимание, что вы можете структурировать это так, чтобы ImageMagick просто запускался как пакетный процесс. Это может быть все, что вам нужно. Однако структурирование ImageMagick в контейнере дает вам возможность подключать разные экземпляры контейнеров ImageMagick, на которых работают разные версии ImageMagick, для одновременного сравнения и тестирования.
Что касается сборки образа из частей других образов, да, прямого способа сделать это нет, но в DockerHub есть примеры образов, состоящих, возможно, из двух разных фреймворков в базовом образе (например, tomcat и JDK), и интеграция дополнительных изменений для установки и настройки другой конкретной платформы в образе просто требует отрывка из вероятного общедоступного файла Dockerfile, в котором показано, как это сделать.