Запись в базу данных flask в докеризованном приложении для сельдерея

#python #docker #flask #celery

Вопрос:

Мне было интересно, каков наилучший подход для достижения этой цели

докер-compose.yml:

 version: '3.8'

services:
  web:
    build: ./services/website
    volumes:
      - ./services/website/src:/usr/src/app/src
      - ./data/cntautomation_logs:/var/log/cntautomation_logs
    expose:
      - 5010
    env_file:
      - .env
    environment:
      - DEPLOYMENT_TYPE=production
    depends_on:
      - db
      - rabbit_mongodb
    entrypoint: ./entrypoint.sh
  db:
    image: postgres
    ports:
      - "5432:5432"
    volumes:
        - postgres_data:/var/lib/postgresql/data/
        - ./data/db_logs:/var/log/postgresql
    environment:
        - POSTGRES_USER=user
        - POSTGRES_PASSWORD=password
        - POSTGRES_DB=database.db
  nginx:
    build: ./services/nginx
    volumes:
      - ./data/nginx_logs:/var/log/nginx
    ports:
      - "80:80"
    depends_on:
      - web

  rabbit:
    hostname: rabbit
    image: "rabbitmq:3-management"
    volumes:
      - ./data/rabbitmq_logs:/var/log/rabbitmq
    env_file:
      - .env
    ports:
      - "15672:15672"
      - "5672:5672"

  rabbit_mongodb:
    image: mongo:latest
    volumes:
      - ./data/rabbit_mongodb_logs:/var/log/mongodb
    command: 
      - '--logpath'
      - '/var/log/mongodb/rabbit_mongodb_log.log'
    ports:
      - "27017:27017"

  worker:
    build: ./services/worker
    user: nobody
    entrypoint: ./entrypoint.sh
    volumes:
      - ./services/worker/app:/usr/src/app/app
      - ./data/worker_logs:/var/log/worker
    env_file:
      - .env
    depends_on:
      - rabbit
      - web
      - rabbit_mongodb
  
volumes:
  postgres_data:
 

У меня есть такой файл для создания докеров. Мне было интересно, как лучше всего написать в мою базу данных postgres в рабочем контейнере сельдерея.

Общим решением, которое я вижу для этого, является создание функции make_celery, которая передается в контексте приложения, но я не вижу, как это будет работать, когда сельдерей и колба разделены на отдельные контейнеры. Одно из решений, о котором я думал, которое, я не уверен, даже сработает, состояло бы в том, чтобы передать контекст приложения в виде маринованного объекта, когда когда-либо задача вызывается по маршруту колбы, а затем выполнить задачу с контекстом приложения. например.

 task.py:
@task(name="task.add")
def add(app, x, y):
    with app.app_context():
        # Write to db
        return x   y

views.py:
@app.route('/add')
def add():
    celery.send_task('task.add', args=[app, 1, 2])
 

Однако я вижу три проблемы с этим подходом:

  1. Я не знаю, как бы я написал в бд с запланированной задачей celery beat.
  2. Могу ли я создать реплику моделей БД flask в рабочем контейнере и создать новый экземпляр sqlalchemy? Или, может быть, передать модель, которую нужно записать, как маринованный объект, как контекст приложения?
  3. Я не видел, чтобы кто-то это делал, так что, вероятно, это даже неприемлемый подход

Мне совсем не нравится это решение, но я не уверен, каким будет стандартный подход

Комментарии:

1. Если я правильно понял, исходный код моделей не разделяется между «вебом» и «работником». Почему это? Не можете ли вы создать файл «модели» и поделиться им между веб-сайтом и рабочим?

2. Справедливо. Сделайте что-то вроде создания томов между контейнерами?. В настоящее время у меня есть мое веб-приложение, структурированное примерно так, как web: {app1: {представления, модели, формы}, app2: {представления, модели, формы}, … и т. Д.}, Поэтому было бы немного сложно смонтировать тома. А как насчет передачи контекста приложения? Считаете ли вы, что приведенное выше решение имеет какой-либо смысл? Я удивлен, что в Интернете не так много комментариев по этому поводу, это похоже на довольно обычную вещь, которую кто-то может сделать. Было бы в целом проще просто переместить работника сельдерея в мой контейнер веб-приложения?

3. Сделайте что-нибудь вроде создания томов между контейнерами? Неееет… просто импортируйте свои модели в рабочее приложение. Сделайте модуль модели доступным для обоих приложений перед упаковкой приложения в контейнер. А как насчет передачи контекста приложения? вам не нужно передавать контекст приложения. Просто создайте новое приложение для колбы на рабочей стороне, используя ту же конфигурацию, и используйте текст app_context этого нового приложения