#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])
Однако я вижу три проблемы с этим подходом:
- Я не знаю, как бы я написал в бд с запланированной задачей celery beat.
- Могу ли я создать реплику моделей БД flask в рабочем контейнере и создать новый экземпляр sqlalchemy? Или, может быть, передать модель, которую нужно записать, как маринованный объект, как контекст приложения?
- Я не видел, чтобы кто-то это делал, так что, вероятно, это даже неприемлемый подход
Мне совсем не нравится это решение, но я не уверен, каким будет стандартный подход
Комментарии:
1. Если я правильно понял, исходный код моделей не разделяется между «вебом» и «работником». Почему это? Не можете ли вы создать файл «модели» и поделиться им между веб-сайтом и рабочим?
2. Справедливо. Сделайте что-то вроде создания томов между контейнерами?. В настоящее время у меня есть мое веб-приложение, структурированное примерно так, как web: {app1: {представления, модели, формы}, app2: {представления, модели, формы}, … и т. Д.}, Поэтому было бы немного сложно смонтировать тома. А как насчет передачи контекста приложения? Считаете ли вы, что приведенное выше решение имеет какой-либо смысл? Я удивлен, что в Интернете не так много комментариев по этому поводу, это похоже на довольно обычную вещь, которую кто-то может сделать. Было бы в целом проще просто переместить работника сельдерея в мой контейнер веб-приложения?
3. Сделайте что-нибудь вроде создания томов между контейнерами? Неееет… просто импортируйте свои модели в рабочее приложение. Сделайте модуль модели доступным для обоих приложений перед упаковкой приложения в контейнер. А как насчет передачи контекста приложения? вам не нужно передавать контекст приложения. Просто создайте новое приложение для колбы на рабочей стороне, используя ту же конфигурацию, и используйте текст app_context этого нового приложения