Создаем и публикуем простой микросервис в Docker

Создаем и публикуем простой микросервис в Docker

В этой статье мы покажем, как создать простейший микросервис на Python Framework FastAPI и запустить его в docker контейнере. Сначала рассмотрим, как скачать и запустить готовый контейнер и базовые команды по управлению контейнером в docker, а затем перейдем к созданию своего образа с микросервисом.

Напомним, что Docker — это программное обеспечение, позволяющее упаковать приложение и все его зависимости в единый модуль. Важное преимущество — процесс развертывания приложения, собранного в контейнер, хорошо интегрируется в CI/CD pipline.

Вкратце, плюсы использования Docker:

  1. Это позволяет нам переносить приложение на другие операционные системы с поддержкой cgroups;
  2. Более эффективно позволяет нагрузить host машину. Не создается виртуальное железо, как при использовании виртуальных машин;
  3. Отлично интегрируется в CI/CD pipline;
  4. Добавляется еще один уровень абстракции, что позволяет использовать на одном хосте различные версии языков, библиотек, 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

status docker active (running)

Если сервис 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)

docker.service inactive (dead) code=exited

Попробуйте запустить службу следующей командой

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

запуск контейнера busybox в интерактивном режиме

Данной командой мы запустили контейнер, с помощью опции -it мы подключили интерактивный tty в контейнер и запустили командную оболочку sh. Ключ —rm позволяет автоматически удалить контейнер при выходе из интерактивного режима.

Внутри контейнера busybox доступны основные команды unix/linux.

Допустим можно посмотреть список директорий:

linux команды в docker образе busybox

Для выхода из контейнера выполните команду:

exit

Следующая команда позволяет просмотреть список доступных локально образов:

sudo docker images

sudo docker images - список доступных локально контейнеров

В конце списка недавно скачанный busybox.

Посмотреть список запущенных контейнеров можно командой:

sudo docker ps -a

Также можно передать фильтр:

sudo docker ps --filter status='exited'

Данная команда, выведет все контейнеры со статусом exited. Это контейнеры, которые остановлены, но не удалены.

sudo docker 'exited' - остановленные контейнеры

Это краткий набор команд, которые используются для запуска контейнера, подключения интерактивного tty в контейнер и входа внутрь контейнера.

Запуск nginx контейнера из образа docker hub

Следующем шагом, мы соберем свой image на основе готового образа. Для этого создадим папку в директории текущего пользователя.

mkdir nginx
cd nginx

В данной папке создадим файл index.html и Dockerfile следующего содержания

index.html

Docker test
I am working in Docker

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 страница, которую мы скопировали в контейнер.

простая html страница в docker контейнере nginx

Чтобы остановить контейнер, выполните:

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.*
Fastapi — это python web framework, позволяющий быстро создавать производительные асинхронные веб сервисы на языке python.

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.

Docker
Создаем и публикуем простой микросервис в Docker