Приложение с несколькими контейнерами: выполнение контейнера из другого контейнера

У меня есть многоконтейнерное приложение 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 внутри того же контейнера.

Вернуться на верх