Приложение с несколькими контейнерами: выполнение контейнера из другого контейнера
У меня есть многоконтейнерное приложение Django. Один контейнер - это база данных, другой - основной webapp с установленным Django для работы с front- и backend. Я хочу добавить третий контейнер, который обеспечивает основную функциональность/инструмент, который мы хотим предложить через webapp. Он имеет несколько сложных зависимостей, поэтому я бы хотел, чтобы он также был отдельным контейнером. Его функциональность обернута в CLI инструмент, и в настоящее время мы собираем образ и запускаем его по мере необходимости, передавая аргументы для CLI инструмента
В настоящее время это файл docker-compose.yml:
version: '3'
services:
db:
image: mysql:8.0.30
environment:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- TZ=${TZ}
volumes:
- db:/var/lib/mysql
- db-logs:/var/log/mysql
networks:
- net
restart: unless-stopped
command: --default-authentication-plugin=mysql_native_password
app:
build:
context: .
dockerfile: ./Dockerfile.webapp
environment:
- MYSQL_NAME=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
ports:
- "8000:8000"
networks:
- net
volumes:
- ./app/webapp:/app
- data:/data
depends_on:
- db
restart: unless-stopped
command: >
sh -c "python manage.py runserver 0.0.0.0:8000"
tool:
build:
context: .
dockerfile: ./Dockerfile.tool
volumes:
- data:/data
networks:
net:
driver: bridge
volumes:
db:
db-logs:
data:
В итоге пользователь должен иметь возможность задать параметры через Web-UI и запустить контейнер инструмента. Множественные процессы должны управляться планировщиком заданий. Я надеялся, что запуск контейнера в многоконтейнерном приложении будет простым, но, насколько я знаю, это возможно только через монтирование сокета docker, чего следует избегать из-за вопросов безопасности.
Итак, мой вопрос: каковы возможности достижения желаемой цели? Вещи, которые я рассматривал:
- multi-stage container: основная цель - уменьшить размер файла, но есть ли хак для использования cli-tool вместе с его собранным окружением в последнем образе многоступенчатого контейнера?
- Api: создайте Api для инструмента. Другие контейнеры могут взаимодействовать через сеть docker. Кажется громоздким .
- Сервис "app" (основное приложение django) построен поверх официального образа python, который я хотел бы сохранить в таком виде. Тем не менее, есть возможность собрать один большой образ на основе Ubuntu, который включает в себя инструмент вместе с его зависимостями и основное приложение django. Это, вероятно, сильно увеличит размеры и может привести к проблемам с зависимостями. .
Кто-нибудь сталкивался с подобными проблемами? На какое направление вы бы мне указали? Я также ищу некоторые слова, которые ускорят мои исследования.
Вы должны собрать обе части в один единый образ, а затем вы можете использовать модуль Python subprocess
как обычно для вызова инструмента.
Стандартный Docker Hub python
образ уже собран на Debian, который очень тесно связан с Ubuntu. Поэтому вы должны быть в состоянии сделать что-то вроде
FROM python:3.10
# Install OS-level dependencies for both the main application and
# the support tool
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
another-dependency \
some-dependency \
third-dependency
# Install the support tool
ADD http://repository.example.com/the-tool/the-tool /usr/local/bin/the-tool
RUN chmod +x /usr/local/bin/the-tool
# Copy and install Python-level dependencies
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Copy in the main application
COPY ./ ./
# Metadata on how to run the application
EXPORT 8000
# USER someuser
CMD ["./the-app.py"]
Вы уже отметили основные проблемы, связанные с размещением инструмента в отдельном контейнере. Обычно вы не можете "выполнять команды" в контейнере; контейнер - это обертка вокруг некоторого отдельного процесса, и для того, чтобы иметь возможность манипулировать контейнером любым способом (включая использование инструмента отладки docker exec
), требуется неограниченный доступ на уровне root к хосту. Вам также потребуется неограниченный доступ на уровне root к хосту, чтобы иметь возможность запускать временный контейнер по запросу.
Создание какого-то API или очереди заданий вокруг инструмента было бы "самым Dockery" способом сделать это, но это также может потребовать значительных усилий по разработке. В описанной вами ситуации инструмент поддержки является в основном деталью реализации основного процесса, поэтому вы не нарушаете правило "один контейнер делает одно дело", делая его доступным для обычного вызова подпроцесса Unix внутри того же контейнера.