Пошаговое руководство по обслуживанию контейнерной модели машинного обучения (ML) с использованием FastAPI и Docker.

В моем предыдущем руководстве мы рассмотрели создание конечных точек для обслуживания модели машинного обучения (ML) для классификатора изображений с использованием Python. и FastAPI.

В этом последующем руководстве мы сосредоточимся на контейнеризации модели с помощью докера при обслуживании через FastAPI.

Если вы следовали моему последнему руководству по обслуживанию предварительно обученной модели классификатора изображений из TensorFlow Hub с использованием FastAPI, вы можете непосредственно перейдите к шагу 3⬇️ этого руководства.😉



Преимущества контейнеризации

Контейнеризация дает следующие преимущества:

  1. Постоянство производительности
    Команды DevOps знают, что приложения в контейнерах будут работать одинаково, независимо от того, где они развернуты.
  2. Более высокая эффективность
    Контейнеры позволяют быстрее развертывать, исправлять или масштабировать приложения.
  3. Меньше накладных расходов
    Контейнеры требуют меньше системных ресурсов, чем традиционные или аппаратные среды виртуальных машин, поскольку они не включают образы операционной системы.

Методология

Мы можем добиться этого, используя 2 подхода.

  1. Реализует aDockerfile, который должен быть built вручную каждый раз при изменении кода, а затем выполняться отдельно.
  2. Автоматизация вышеупомянутого процесса с помощью docker-compose

Шаг 0: Предпосылки

  1. Питон 3.6+
  2. У вас установлен docker.
  3. Создайте структуру проекта следующим образом
fastapi-backend
├── src
│   ├── app
│   │   ├── app.py
│   └── pred
│   │   ├── models
│   │   │   ├── tf_pred.py
│   │   └── image_classifier.py
│   └── utils
│   │   ├── utilities.py
│   └── main.py
├── Dockerfile
├── docker-compose.yml
└── requirements.txt

Шаг 1: Настройка

В файле app.py реализуйте конечную точку /predict/tf/, используя FastAPI.

В файле main.py мы используем сервер uvicorn, который представляет собой реализацию веб-сервера ASGI для Python.

Примечание. Поскольку целью руководства является контейнеризация приложения, подробное объяснение приведенного выше фрагмента было объяснено в шаге 2 раздела >предыдущий руководство.

Шаг 2: Создайте Dockerfile

Первым шагом для контейнеризации приложения является создание файла Dockerfile в каталоге вашего проекта (см. структуру проекта выше).

Dockerfile — это текстовый документ, содержащий все инструкции, необходимые для создания образа докера.

Мы определяем наш Dockerfile следующим образом:

Пояснения:

  • Line 1 : загружает указанный образ Docker (python:3-buster) из реестра docker hub. Вы можете проверить доступные изображения здесь.
  • Line 3 : Обновляет pip, чтобы позже мы могли установить requirements.txt
  • Line 4 : Устанавливает рабочий каталог в /code . Это необходимо для того, чтобы все скрипты запускались из общего родительского каталога
  • Line 6 : копирует файл requirements.txt и его содержимое с хоста в контейнер.
  • Line 7: Устанавливает содержимое requirements.txt внутрь образа.
  • Lines 9–12 : Копирует соответствующие файлы с хоста в образ.
  • Line 13: инструкция CMD (исполняемая) используется для установки команды, которая будет выполняться при запуске контейнера. Dockerfile должна иметь только одну инструкцию CMD, а в случае их нескольких действует только последняя. Этот оператор также устанавливает команду по умолчанию для контейнера python main.py .

Шаг 4. Создайте и запустите приложение

После того, как мы внедрили наш Dockerfile, следующим шагом будет build образ докера, а затем run его.

Шаг 4.1. Создайте изображение

Мы строим образ (здесь myfastapiimage ) следующим образом.
Вы можете назвать его любым именем по вашему выбору.

docker build -t myfastapiimage .

Важные замечания:

  • Не забудьте . после изображения
  • Если ваш образ Docker не перестраивается после изменения файлов, вы можете инициировать принудительную сборку следующим образом:
docker build --no-cache -t myfastapiimage .

docker build обычно использует кеш для ускорения работы. --no-cache гарантирует, что принудительно перестроит его.

Шаг 4.2. Запустите контейнер

docker run --name mycontainer -p 80:8000 myfastapiimage

Пояснения

  • docker run --name <myContainerName> : создает контейнер с именем mycontainer (здесь вы можете использовать любое имя). Имя контейнера позже используется для целей идентификации.
  • -p <host_port>:<container_port> сопоставляет порт хоста (80) с портом контейнера (8000).
  • myfastapiimage — это имя образа, из которого создан контейнер.

[Альтернатива шагу 4] Используйте Docker-compose

docker-compose — это инструмент, идеально подходящий для определения и запуска многоконтейнерных приложений Docker. В Compose мы используем YAML file (.yml) для настройки служб приложения.

Самым большим преимуществом использования docker-compose является то, что с помощью одной команды мы создаем и запускаем все службы из нашей конфигурации. Вы можете прочитать больше о docker-compose здесь.

Теперь давайте посмотрим, как мы определяем docker-compose в нашем случае. Поскольку наше приложение представляет собой одно сервисное приложение, определение docker-compose должно быть довольно простым.

Пояснения:

  • В этом docker-compose определена одна служба с именем app.
  • Служба app использует образ, созданный из Dockerfile в текущем каталоге.
  • Затем он привязывает контейнер и хост-компьютер к открытому порту 8000.
  • Он также привязывает /src/ от хоста к контейнеру. Привязка тома необходима для отражения любых изменений файлов на хосте в контейнере.

Выполняетсяdocker-compose :

Из каталога проекта запустите приложение, выполнив следующую команду.

docker-compose up --build

Посетите http://127.0.0.1:8000/ в браузере, чтобы запустить приложение.

Несколько полезных советов по отладке

  • Если у вас возникли проблемы с изображением, вы можете попытаться проникнуть внутрь оболочки контейнера и отладить ее. Чтобы врезаться в работающий контейнер, введите следующее:
docker exec -t -i mycontainer /bin/bash
  • Если ваш образ Docker не перестраивается после изменения файлов, вы можете инициировать принудительную сборку следующим образом:
docker build --no-cache -t myfastapiimage .
  • Иногда, если вы попытаетесь повторно запустить док-контейнер, вы можете получить ошибку container already in use. В этом случае завершите работу контейнера, удалите его с помощью docker rm <containerName> и перезапустите свой контейнер.
    Или, если вы используете docker-compose, вы также можете ввести следующее из терминала (внутри каталога проекта):
docker-compose down
  • В случае path errors будьте осторожны с container roots, который вы используете, и соответствующим образом настройте пути.
  • Также еще одна удобная команда докера:
docker ps -a 

Он предоставляет вам весь список всех контейнеров (запущенных и остановленных).

Заключение

В этом руководстве мы узнали, как контейнеризовать наше приложение с помощью Docker.

Следующим шагом после контейнеризации является развертывание.
Когда мы довольны поведением нашего контейнерного приложения, мы можем развернуть его в любой управляемой/гибридной/локальной облачной службе с минимальным риском сбоя.

Примечание. Это руководство можно распространить на любой тип контейнеризации приложений, а не только на приложение FasAPI.
Вам просто нужно настроить Dockerfile и docker-compose соответственно. Остальное остается прежним
😉.

Исходный код на GitHub доступен здесь.
Ссылки и дополнительная литература по этой теме собраны здесь.

Если вам понравилась статья, подпишитесь, чтобы получать мои последние статьи.
Чтобы связаться со мной, либо свяжитесь со мной в LinkedIn или через ashmibanerjee.com.