diff --git a/DOCS/howto-flask-nubes.md b/DOCS/howto-flask-nubes.md new file mode 100644 index 0000000..d41d78b --- /dev/null +++ b/DOCS/howto-flask-nubes.md @@ -0,0 +1,124 @@ +# Как писать Flask-приложение для Nubes + +## Структура папок (ОБЯЗАТЕЛЬНО) + +``` +repo/ +├── requirements.txt +└── site/ + ├── app.py # точка входа + ├── static/ + │ └── style.css + └── templates/ + └── index.html +``` + +**БЕЗ `site/` папки — НЕ ЗАПУСТИТСЯ.** Платформа ждёт именно `site/app.py`. + +## app.py — точка входа + +### Минимальный рабочий вариант: + +```python +from flask import Flask, render_template + +app = Flask(__name__, template_folder="templates", static_folder="static") + +@app.route("/") +def index(): + return render_template("index.html") + +if __name__ == "__main__": + app.run(debug=True, host="0.0.0.0", port=5000) +``` + +### КЛЮЧЕВЫЕ МОМЕНТЫ: + +1. **`if __name__ == "__main__": app.run(host="0.0.0.0", port=5000)` — ОБЯЗАТЕЛЬНО!** + Платформа запускает `python site/app.py`. Без `app.run()` скрипт определит `app` и выйдет — контейнер упадёт. + +2. **`template_folder="templates"`, `static_folder="static"` — указывать явно.** + Без них Flask может не найти шаблоны при запуске из корня репо. + +3. **`debug=True`** — как в рабочем шаблоне. На проде заменить на `False`. + +## Модули (если нужно) + +Можно дробить на модули внутри `site/`: + +``` +site/ +├── app.py +├── api/ +│ └── http_client.py +├── operations/ +│ └── get_instances.py +├── routes/ +│ └── main.py +├── static/ +└── templates/ +``` + +### Импорты внутри site/: + +```python +# app.py +from routes.main import bp as main_bp +app.register_blueprint(main_bp) +``` + +```python +# routes/main.py +from api.http_client import HttpClient +from operations.get_instances import get_organization +``` + +**НЕ НУЖЕН `sys.path.insert`!** При запуске `python site/app.py` Python сам добавляет `site/` в `sys.path[0]`. + +### ⛔ НЕЛЬЗЯ: + +- **`site/__init__.py`** — удалить! Конфликтует со stdlib `site.py`, ломает импорты. +- **`from site.xxx import ...`** — никогда. Импорт всегда без префикса `site.` +- **Factory pattern (`create_app()`)** — платформа ждёт `app` на уровне модуля. + +## requirements.txt + +```txt +Flask>=3.0 +gunicorn>=21.2 +requests>=2.31 +``` + +## Переменные окружения (jsonEnv в параметрах сервиса) + +```json +{ + "NUBES_API_TOKEN": "...", + "NUBES_API_ENDPOINT": "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" +} +``` + +В коде читать через `os.getenv("NUBES_API_TOKEN", "")`. + +## Деплой + +- `gitPath`: URL репозитория +- `jsonEnv`: переменные окружения +- `healthPath`: можно оставить `""` + +## Отладка + +Если под не стартует — смотреть логи в кубере: +```bash +kubectl -n logs deploy/pythonk8s --tail=50 +kubectl -n get pods +``` + +## Частые ошибки + +| Ошибка | Причина | Решение | +|--------|---------|---------| +| Под Completed, рестарты | Нет `app.run()` | Добавить `if __name__ == "__main__": app.run(...)` | +| ModuleNotFoundError | Есть `site/__init__.py` | Удалить `site/__init__.py` | +| 500 на / | API недоступен или токен неверный | Обернуть в try/except | +| Нет папки site/ | Другая структура | Всегда `site/app.py` |