В этой статье мы покажем, как создать простейший микросервис на Python Framework FastAPI и запустить его в docker контейнере. Сначала рассмотрим, как скачать и запустить готовый контейнер и базовые команды по управлению контейнером в docker, а затем перейдем к созданию своего образа с микросервисом.
Напомним, что Docker — это программное обеспечение, позволяющее упаковать приложение и все его зависимости в единый модуль. Важное преимущество — процесс развертывания приложения, собранного в контейнер, хорошо интегрируется в CI/CD pipline.
Вкратце, плюсы использования Docker:
- Это позволяет нам переносить приложение на другие операционные системы с поддержкой cgroups;
- Более эффективно позволяет нагрузить host машину. Не создается виртуальное железо, как при использовании виртуальных машин;
- Отлично интегрируется в CI/CD pipline;
- Добавляется еще один уровень абстракции, что позволяет использовать на одном хосте различные версии языков, библиотек, etc.
Основные команды управления docker engine
В статье мы опустим процесс установки docker в Linux (предполагаем, что вы уже сделали это). Давайте для начала убедимся, что у вас установлена и работает служба docker. Выполните в терминале команду
sudo systemctl status docker
Вывод должен быть примерно такой:
● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled) Active: active (running) since Tue 2021-02-16 16:14:48 +05; 4h 58min ago Docs: https://docs.docker.com Main PID: 20976 (dockerd) Tasks: 57 CGroup: /system.slice/docker.service ├─20976 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ├─27968 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5432 -container-ip 172.17.0.2 -container-port 5432 └─28315 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 18000 -container-ip 172.17.0.3 -container-port 18000
Если сервис Docker не запущен, вывод команды будет примерно такой:
● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled) Active: inactive (dead) since Tue 2021-02-16 21:17:32 +05; 1s ago Docs: https://docs.docker.com Process: 20976 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=0/SUCCESS) Main PID: 20976 (code=exited, status=0/SUCCESS)
Попробуйте запустить службу следующей командой
sudo systemctl start docker
Если все прошло без ошибок, можно переходить к следующему шагу.
Если вывелось такое сообщение:
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
значит служба не запустилась и нужно смотреть журнал и разбираться с проблемой. Следующая команда выведет содержимое журнала сервиса dockerd:
sudo journalctl -xe /usr/bin/dockerd
Запуск первого контейнера в Docker
Итак, у вас запушен Docker и вы можете запустить первый контейнер. Выполните в консоли команду:
sudo docker pull busybox
Данной командой, мы скачали готовый образ busybox с сервера Docker Hub. Docker hub – это публичнй репозиторий docker образов. Он предоставляет возможность хранить свои image , обмениваться ими с другими людьми. В данном репозитории собраны множество готовых образов с популярным ПО. Busybox — это собранное в одном исполняемом файле набор утилит unix.
sudo docker run -it --rm busybox sh
Данной командой мы запустили контейнер, с помощью опции -it мы подключили интерактивный tty в контейнер и запустили командную оболочку sh. Ключ —rm позволяет автоматически удалить контейнер при выходе из интерактивного режима.
Внутри контейнера busybox доступны основные команды unix/linux.
Допустим можно посмотреть список директорий:
Для выхода из контейнера выполните команду:
exit
Следующая команда позволяет просмотреть список доступных локально образов:
sudo docker images
В конце списка недавно скачанный busybox.
Посмотреть список запущенных контейнеров можно командой:
sudo docker ps -a
Также можно передать фильтр:
sudo docker ps --filter status='exited'
Данная команда, выведет все контейнеры со статусом exited. Это контейнеры, которые остановлены, но не удалены.
Это краткий набор команд, которые используются для запуска контейнера, подключения интерактивного tty в контейнер и входа внутрь контейнера.
Запуск nginx контейнера из образа docker hub
Следующем шагом, мы соберем свой image на основе готового образа. Для этого создадим папку в директории текущего пользователя.
mkdir nginx
cd nginx
В данной папке создадим файл index.html и Dockerfile следующего содержания
index.html
<html> <title>Docker test</title> <body>I am working in Docker</body> </html>
Dockerfile
FROM nginx COPY index.html /usr/share/nginx/html
В файле Dockerfile с помощью директивы FROM мы указали что нужно использовать использовать image nginx. Команда COPY позволяет скопировать из текущей директории файл index.html в папку /usr/share/nginx/html в образе.
Выполните в директории nginx команду:
sudo docker build . --tag mynginx
Данная команда скачает с docker hub официальный образ nginx последней доступной версии. Новый локальный образ будет помечен тегом mynginx:latest
Теперь можно запустить контейнер, используя собранный image:
sudo docker run -p 8080:80 -d --name nginx_test mynginx
Данной командой мы запустили контейнер. Опция -p нужна чтобы пробросить порт 80 контейнера на порт host машины 8080. Опция -d позволяет запустить контейнер в фоновом режиме без привязки к текущей консоли, опция —name задает имя контейнеру.
Чтобы проверить работу nginx в образе, откройте браузер и перейдите по адресу
http://localhost:8080/
. Перед вами должна открыться html страница, которую мы скопировали в контейнер.
Чтобы остановить контейнер, выполните:
sudo docker stop nginx_test
Чтобы удалить контейнер:
sudo docker rm nginx_test
Создаем простой микросервис на python framework FastAPI
Создадим структуру проекта:
~# mkdir fpdc
~# cd fpdc
Создадим в директории fpdc два файла requirements.txt и main.py. Файл main.py будет точкой входа для запуска приложения, файл requirements.txt — это зависимости.
Добавим в файл requirements.txt следующие зависимости:
fastapi==0.63.* uvicorn==0.13.*
Uvicorn — это легковесный asgi сервер. С помощью него можно запускать веб сервисы, написанные с использование fastapi, django, flask и других.
Содержимое файла main.py
from fastapi import FastAPI app = FastAPI(title="Test microsevice") @app.get("/api/v1/hello") def hello(name: str = ""): return {"msg": f"Hello {name}"}
Данной строкой мы создаем asgi приложение:
app = FastAPI(title="Test microsevice")
После мы создаем функцию обработчик маршрута(router):
@app.get("/api/v1/hello")
def hello(name: str = ""):
return {"msg": f"Hello {name}"}
Строка над функцией – это декортатор, он добавляет маршрут в наше приложение.
Теперь создадим Dockerfile со следующем содержимым:
FROM python:3.7.7-slim
RUN mkdir /app
COPY ./main.py /app
WORKDIR /app/
COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
EXPOSE 8000
CMD ["uvicorn", "--host", "0.0.0.0", "main:app"]
Dockerfile – похож на makefile, в нем так же указаны команды, но только для сборки контейнера. Давайте разберем команды подробнее.
FROM
– данная инструкция задает базовый образ (image) для сборки.
RUN
– выполняет произвольные shell команды. В данном случае, создает директорию /app
COPY
– копирует файлы с хост машины в докер контейнер.
EXPOSE
– указывает, что контейнер слушает порт 8000 при запуске.
CMD
– указывает, какую команду выполнить при запуске контейнера.
В данном примере, мы запускаем сервер uvicorn, указав, что он будет прослушивать все интерфейсы и что нужно запустить наше приложение.
Минимальный сервис создан, можно собрать контейнер.
sudo docker build . --tag microsevice_v1
И запустить получившийся сервис:
sudo docker run -p 8000:8000 -d --name micro_v1 microsevice_v1
Работу сервиса можно проверить из консоли:
curl -X GET "http://127.0.0.1:8000/api/v1/hello" -H "accept: application/json"
curl -X GET "http://127.0.0.1:8000/api/v1/hello?name=World%20" -H "accept: application/json"
Или можно зайти в браузер и выполнить данные запросы. Большим плюсом фреймворка FastAPI является то, что он автоматически генерирует документацию к API, которая доступна по адресу:
http://localhost:8000/docs/
Минимальный работающий микросервис создан и запущен в docker контейнере. В следующий статьях функционал будет расширен, создадим композицию сервисов, подключим базу данных, добавим frontend. В дальнейшем, запустим данный сервис в среде kubernetes.