Минимальная демка общения нескольких Python-приложений через Redis в Docker:
api— FastAPI-приложение, которое принимает задачи и отдает результаты.alloy— собирает логи Docker-контейнеров и отправляет их в Loki.frontend— легкая HTML-страница для запуска задач из браузера.grafana— UI для просмотра логов.loki— хранилище логов.worker_double— отдельный worker для задачиx * 2.worker_square_plus_one— отдельный worker для задачиx^2 + 1.redis— очередь и хранилище результатов.
docker compose up --buildAPI будет доступен на порту из .env:
API_PORT=8000
FRONTEND_PORT=8080
GRAFANA_ADMIN_PASSWORD=admin
GRAFANA_ADMIN_USER=admin
GRAFANA_PORT=3000
LOKI_PORT=3100
REDIS_PORT=6379Демо-страница будет доступна по адресу:
http://localhost:8080
Grafana будет доступна по адресу:
http://localhost:3000
Логин по умолчанию:
admin / admin
Эти значения вынесены в .env:
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=admincurl -X POST http://localhost:8000/tasks/double \
-H "Content-Type: application/json" \
-d '{"x": 21}'Пример ответа:
{"task_id":"8d393ca5-4f9f-48e7-b5d1-cbe32ce6e0d3","status":"queued"}curl -X POST http://localhost:8000/tasks/square-plus-one \
-H "Content-Type: application/json" \
-d '{"x": 5}'Пример ответа:
{"task_id":"9ec6293d-5628-47fd-8d45-e9e80a9801f4","status":"queued"}curl http://localhost:8000/tasks/<task_id>Пример ответа во время обработки:
{"task_id":"8d393ca5-4f9f-48e7-b5d1-cbe32ce6e0d3","status":"processing"}Пример ответа после обработки:
{"task_id":"8d393ca5-4f9f-48e7-b5d1-cbe32ce6e0d3","status":"done","result":42}Если отправить запрос без поля x, API вернет 422:
curl -X POST http://localhost:8000/tasks/double \
-H "Content-Type: application/json" \
-d '{}'На странице есть:
- поле ввода числа
- кнопка
Run x * 2 - кнопка
Run x² + 1 - автоматический опрос статуса задачи до получения результата
После запуска:
- Открой
http://localhost:3000 - Войди как
admin / admin - Перейди в
Explore - Выбери источник данных
Loki - Пример запроса:
{job="docker"}
Пример для логов API:
{container=~".*api.*"}
Пример для логов worker'а:
{container=~".*worker_double.*"}
.
├── .env
├── README.md
├── alloy-config.alloy
├── api
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
├── docker-compose.yml
├── frontend
│ ├── Dockerfile
│ └── index.html
├── grafana
│ └── provisioning
├── worker_double
│ ├── Dockerfile
│ ├── requirements.txt
│ └── worker.py
└── worker_square_plus_one
├── Dockerfile
├── requirements.txt
└── worker.py