Пошаговое руководство по обслуживанию контейнерной модели машинного обучения (ML) с использованием FastAPI и Docker.
В моем предыдущем руководстве мы рассмотрели создание конечных точек для обслуживания модели машинного обучения (ML) для классификатора изображений с использованием Python. и FastAPI.
В этом последующем руководстве мы сосредоточимся на контейнеризации модели с помощью докера при обслуживании через FastAPI.
Если вы следовали моему последнему руководству по обслуживанию предварительно обученной модели классификатора изображений из TensorFlow Hub с использованием FastAPI, вы можете непосредственно перейдите к шагу 3⬇️ этого руководства.😉
Преимущества контейнеризации
Контейнеризация дает следующие преимущества:
- Постоянство производительности
Команды DevOps знают, что приложения в контейнерах будут работать одинаково, независимо от того, где они развернуты. - Более высокая эффективность
Контейнеры позволяют быстрее развертывать, исправлять или масштабировать приложения. - Меньше накладных расходов
Контейнеры требуют меньше системных ресурсов, чем традиционные или аппаратные среды виртуальных машин, поскольку они не включают образы операционной системы.
Методология
Мы можем добиться этого, используя 2 подхода.
- Реализует a
Dockerfile
, который должен бытьbuilt
вручную каждый раз при изменении кода, а затем выполняться отдельно. - Автоматизация вышеупомянутого процесса с помощью
docker-compose
Шаг 0: Предпосылки
- Питон 3.6+
- У вас установлен docker.
- Создайте структуру проекта следующим образом
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.