Павло Щербуха

Logo

Персональна освітня сорінка

Розробка на Node.js, VUE.js, Python, IBM Integration Bus (App Connect Ent) , ORACLE PL/SQL
2 September 2022

Python - flask debug додатку, що запущено в контейнері

by Pavlo Shcherbukha

Зміст

  1. Про що цей блог
  2. Різниця в запуску flask application
  3. Підготовка Dockerfile
  4. Підготовка файлів типу docker-compose для запуску в різних режимах
  5. Налаштування Visual Studio Code
  6. Запуск та підключення до debug з Visual Studio COde

1. Про що цей блог

Це продовження записок початківця про python flask. В попреденіх серіях було про запуск flask application в контейнері і через docker-compose поєднати з супутнім сервісов. В якості супутнього сервісу було вибрано Redis DB. Але в усіх цих випадках сервіс Python запускався я продуктивному режимі. Але, не маючи режима debug в контейнері ефективно розробляти не зручно. В цьому блозі:

Як налаштувати можливість debug python-flask application, що запущено в контейнері, викорстовуючи docker-compose. Я довго це пробував зібрати до купи. Але цей метод мені здався найбільш дієвим. Тут мова піде не про програмування, а більше про devops навики. Але, якщо розробник не матиме цих навиків, то як йому на своєму laptop створити середовище розробки і ефективно працювати? Як правильно зпроектувати, які компоненти винести в параметризацію?…. Ну і ще можна знайти купу таких риторичних запитань.

Репозиторій з прикладом доступний за лінком: py-flask-app-smpl-redis-dbg Flask application. Debug додатку, що запущено в контейнері.

2. Різниця в запуску flask application

Flask template розроблений таким чином, що його можна запустити в development mode, як описано в Створення найпростішого скрипта для flask app та запуск applicaiton з індивідуальною назвою в DEVELOPENT mode. А бо ж flask application запускається в productive mode за WSGI сервером типу gunicorn, як описано в Python - flask запуск в контейнері від RadHat UBI8.

Збірка запуск та debug контейнера з сервісом python описана за цими лінками:

Але, воно мене не дуже влаштовує, так як запускає окремий контейнер. А мені потрібно підняти локально кілька компонентів через docker-compose, які “бачать” один одного в мережі а вже потім підключати debug.

Раптом мені попалася бібліотека від Microsoft, що забезепечує взаємодію debug протоколу python додатків та Visual Studio Code: ptvsd або ж лінк на github Python Tools for Visual Studio debug server. Також, зандобилася бібліотека debugpy , або на github debugpy - a debugger for Python.

Таким чином, мені для запуску debug потрібно:

Підготовка Dockerfile

Для запуску в *productive mode** Dockerfile виглядава таким чином:

FROM registry.fedoraproject.org/f33/python3
# Add application sources to a directory that the assemble script expects them
# and set permissions so that the container runs without root access
USER 0
COPY . /tmp/src
RUN /usr/bin/fix-permissions /tmp/src
USER 1001

# Install the dependencies
RUN python3.9 -m pip install --upgrade pip
RUN /usr/libexec/s2i/assemble
EXPOSE 8080
# Set the default command for the resulting image
CMD /usr/libexec/s2i/run

Тепер використаємо властивість Dockerfile multistage-build. Сенс використаня multistage-build в тому, що ми можемо використати кілька команд FROM з аліасом. Основний сенс цик команд в наступному:

Ось останню особливість і використаємо. А при старті docker-compose вкажемо, яка stage мається на увазі у тезі target : Compose file version 3 reference

pic-01

Ось наведено Dockerfile який в результаті отримав:

FROM registry.fedoraproject.org/f33/python3 as base
# Add application sources to a directory that the assemble script expects them
# and set permissions so that the container runs without root access
USER 0
COPY . /tmp/src
RUN /usr/bin/fix-permissions /tmp/src
USER 1001

# Install the dependencies
RUN python3.9 -m pip install --upgrade pip
RUN /usr/libexec/s2i/assemble
EXPOSE 8080

FROM base as debug
RUN pip install ptvsd debugpy
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE 1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED 1
EXPOSE 5678

FROM base as prod
# Set the default command for the resulting image
CMD /usr/libexec/s2i/run

А на pic-02 показані коротке пояснення, як stage з Dockerfile відображається на yaml з docker compose

pic-02

Підготовка файлів типу docker-compose для запуску в різних режимах

Потрібно не забути, що при запуску в режимі debug, flask app потрібно запускати поза gunicorn, командою pyhon flask run ну з розширенням спеціальним ключами під debug. В нашому випадку:

python -m debugpy --listen 0.0.0.0:5678 --wait-for-client -m flask run -h 0.0.0.0 -p 8080

На pic-03 показана порівняльна характеристика docker-comppose - файлів для різних режимів запуску, що будуються з єдного dockerfile.

pic-03

Налаштування Visual Studio Code

Для налаштування Visual Studio Code потрібно в файл: “.vscode/launch.json” блок для підключення:

    {
        "name": "Sh-FLASK-Python: Remote Attach",
        "type": "python",
        "request": "attach",
        "port": 5678,
        "host": "0.0.0.0",
        "pathMappings": [
            {
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "/opt/app-root/src"
            }
        ]
    }

В полі remoteRoot потрібно вказати каталог де знаходиться програмний код вашого додатку в контейнері. Для UBI8 це /opt/app-root/src. А в приципі, можна отримати, якщо підключится до контейнера перейти в ваш каталог та виконати команду linux pwd.

Запуск та підключення до debug з Visual Studio COde

Ну і тепер порібно це все запустити.

docker-compose -f docker-compose-debug.yaml up --build smplapp-srvc-redis
docker-compose -f docker-compose-prod.yaml up --build smplapp-srvc-redis

Для швидкого запуску я виніс запуск docker-compose у sh-composer-up-dev.cmd та sh-composer-up-prod.cmd

Для запуску в режимы Debug запускаємо sh-composer-up-dev.cmd.

Спершу виконується побудова образу, потім контейнер запускається і завмирає на Attachin to …… (обведено червоною рамочкою на pic-04)

pic-04

В цей момент потріно переклчитися на Visual Studio Code та вирати налаштований вами в попередньому пункті режим підключення до контейнера pic-05

pic-05

І от диво, сервіс стартонув у контейнері pic-06

pic-06

Ну а якщо відкрити файл view.py поставити brakepoint на обробнику метода /api/health то отримаємо зупинку програми при зверенні до http://localhost:8081/api/health як на pic-07.

pic-07

Якщо ж виконати запуск в продуктивному режимі, то на pic-08 видно як воно швидко стартує, та ще й в 4 потоках (там для кожного pid в лог записується).

pic-08

Ну, таким чином, можна вважати що Remote Debug для Flask app , що запущено в контейнері виконано.

tags: