Используем Docker для python приложения

10/02/2020

docker img

Технология контейнеризации Docker — своеобразная священная корова последних лет в области Информационных Технологий. Именно с помощью Docker и различных систем управления для контейнеров получается реализовать самые высоконагруженные системы в мире. Также заметно упрощается процесс разработки приложений. В свое время уже писал в блоге статью из этой области — Docker в повседневной работе ITшника. Сейчас хотелось бы немного больше осветить практическую часть вопроса. А именно способ запуска python приложения в Docker контейнере на сервере. При этом подразумевается, что Вы не используете инфраструктуру наподобие Kubernetes или его аналогов, а просто хотите по мере необходимости использовать контейнеры от случая к случаю. Частенько бывает ситуация, что сервер для различных задач задействует возможности Python v2. При этом есть существенная необходимость запускать приложения, написанные на Python v3. Использование Docker позволяет элегантно решить эту задачу.

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

Что делать

В первую очередь необходимо установить сам Docker, с помощью которого мы будем собирать образ и запускать контейнер с нашим приложением Python. Для разных дистрибутивов есть соотвествующие руководства на сайте docker.com. Так для Ubuntu можно почитать по этой ссылке. Вкратце последовательность команд в консоли Ubuntu Linux будет следующая:

$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

После проведенных манипуляций мы получим работающий Docker в системе. Это можно проверить с помощью команды docker version. Пример вывода данной команды представлен ниже.

$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:50:12 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:48:43 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683 

Когда мы проверили, что установка Docker прошла успешна, пришло время для создания образа контейнера, в котором мы будем запускать наше приложение. В качестве приложения будем использовать telegram бот, создание которого я описывал в статье — Telegram боты и их создание. Создадим Dockerfile со следующим содержанием, который позволит на базе образа python из Docker Hub получить нужный нам контейнер.

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY bot.ini bot.ini
COPY bot.py bot.py

CMD [ "python", "./bot.py" ] 

В файле requirements.txt содержится список модулей Python, которые будут установлены с помощью менджера пакетов pip в контейнер. Этот файл, а также прочие файлы, которые с помощью директивы COPY будут помещены в образ создаваемого контейнера должны находиться в той же директории, что и Dockerfile. Содержание requirements.txt для данного примера приведено ниже.

python-telegram-bot
emoji

В файле bot.py у нас содержится непосредственно код telegram бота, который будет запускаться в контейнере. А в файлике bot.ini — первоначальные кофигурационные данные для запуска приложения. После того, как все вышеуказанные файлы будут готовы, можно приступать к сборке образа контейнера. Это делается с помощью следующей команды.

$ docker build -t python-docker-app .

Мы получили нужный образ, который можем запускать для работы в продакшене. Это можно делать через утилиту командной строки docker run, а можно и с помощью скрипта systemd. В случае со скриптом systemd мы получим сервис, которым можно будет полноценно управлять системными средствами. То есть, данное приложение можно будет запускать автоматически при старте сервера, а также следить за его постоянной работоспособностью. Пример такого скрипта приведен ниже.

[Unit]
Description=Python Script in Docker
Requires=docker.service
After=docker.service

[Service]
Restart=always
RestartSec=3
ExecStartPre=/bin/sh -c "/usr/bin/docker rm -f my-running-app 2> /dev/null || /bin/true"
ExecStart=/usr/bin/docker run --rm --name my-running-app python-docker-app
ExecStop=/usr/bin/docker stop my-running-app

[Install]
WantedBy=multi-user.target

Данный скрипт размещаем в директории /etc/systemd/system. Назовем его к примеру — docker-python.service. После того, как он будет готов, выполняем команду # systemctl daemon-reload. Теперь наше докеризированное приложение может запускаться, останавливаться и управляться с помощью системной утилиты service.

Резюме

Небольшой пример из данной статьи показывает реальный жизненный кейс о том, как запускать Python приложение в отдельном контейнере на обычном Linux сервере. Если Вы занимаетесь этим на постоянной основе, то разделив различные приложения по отдельным контейнерам, можно отлично использовать один общий виртуальный или физический сервер для целей их хостинга. При этом одно приложение никоим образом не будет влиять на другое. Вопросы синтаксиса при написании Dockerfile не рассматривал в данной статье. Также упор был сделан на запуск приложения, которое использует только один собственный контейнер. О том, как работать с многоконтейнерными приложениями, мы поговорим в следующих статьях этого блога.

Добавить комментарий

Ваш адрес email не будет опубликован.