Как собрать и развернуть приложение Flask с помощью Docker в Ubuntu 18.04

_Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations. _

Вступление

Docker - это приложение с открытым исходным кодом, которое позволяет администраторам создавать, управлять, развертывать и реплицировать приложения с использованием контейнеров. Контейнеры можно рассматривать как пакет, в котором хранятся зависимости, необходимые приложению для запуска на уровне операционной системы. Это означает, что каждое приложение, развернутое с помощью Docker, живет в собственной среде, и его требования обрабатываются отдельно.

Flask - это веб-микро-фреймворк, созданный на Python. Он называется микро-фреймворком, потому что для его работы не требуются специальные инструменты или плагины. Каркас Flask легкий и гибкий, но в то же время хорошо структурированный, что делает его предпочтительным по сравнению с другими каркасами.

Развертывание приложения Flask с помощью Docker позволит вам реплицировать приложение на разные серверы с минимальной перенастройкой.

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

Предпосылки

Чтобы следовать этому уроку, вам понадобится следующее:

Шаг 1 - Настройка приложения Flask

Для начала вы создадите структуру каталогов, которая будет содержать ваше приложение Flask. Этот учебник создаст каталог с именем + TestApp + в + / var / www +, но вы можете изменить команду так, чтобы она называлась как угодно.

sudo mkdir /var/www/

Перейдите во вновь созданный каталог + TestApp +:

cd /var/www/

Затем создайте структуру базовой папки для приложения Flask:

sudo mkdir -p app/static app/templates

Флаг + -p + указывает, что + mkdir + создаст каталог и все родительские каталоги, которые не существуют. В этом случае + mkdir + создаст родительский каталог + app + в процессе создания каталогов + static + и + templates +.

Каталог + app + будет содержать все файлы, связанные с приложением Flask, такие как views и blueprints. Views - это код, который вы пишете для ответа на запросы к вашему приложению. Blueprints создают компоненты приложения и поддерживают общие шаблоны в приложении или в нескольких приложениях.

В каталоге + static + находятся ресурсы, такие как изображения, файлы CSS и JavaScript. Каталог + templates + - это то место, куда вы поместите шаблоны HTML для вашего проекта.

Теперь, когда структура базовой папки завершена, создайте файлы, необходимые для запуска приложения Flask. Сначала создайте файл + init . Py внутри каталога` + app`. Этот файл сообщает интерпретатору Python, что каталог + app + является пакетом и должен рассматриваться как таковой.

Выполните следующую команду, чтобы создать файл:

sudo nano app/__init__.py

Пакеты в Python позволяют группировать модули в логические пространства имен или иерархии. Такой подход позволяет разбить код на отдельные и управляемые блоки, выполняющие определенные функции.

Затем вы добавите код в + init . Py +, который создаст экземпляр Flask и импортирует логику из файла + views.py +, который вы создадите после сохранения этого файла. Добавьте следующий код в ваш новый файл:

/var/www/TestApp/init.py

from flask import Flask
app = Flask(__name__)
from app import views

После добавления этого кода сохраните и закройте файл.

Создав файл + init . Py +, вы готовы создать файл + views.py + в каталоге + app +. Этот файл будет содержать большую часть логики вашего приложения.

sudo nano app/views.py

Затем добавьте код в файл + views.py +. Этот код вернет строку + hello world! + Пользователям, которые посещают вашу веб-страницу:

/var/www/TestApp/app/views.py

from app import app

@app.route('/')
def home():
  return "hello world!"

Строка + @ app.route + над функцией называется decorator. Декораторы модифицируют функцию, которая следует за ним. В этом случае декоратор сообщает Flask, какой URL вызовет функцию + home () +. Текст + hello world +, возвращаемый функцией + home +, будет отображаться пользователю в браузере.

Имея файл + views.py +, вы готовы создать файл + uwsgi.ini +. Этот файл будет содержать конфигурации https://uwsgi-docs.readthedocs.io [uWSGI] для нашего приложения. uWSGI - это вариант развертывания для Nginx, который является одновременно протоколом и сервером приложений; сервер приложений может обслуживать протоколы uWSGI, FastCGI и HTTP.

Чтобы создать этот файл, выполните следующую команду:

sudo nano uwsgi.ini

Затем добавьте следующее содержимое в ваш файл для настройки сервера uWSGI:

/var/www/TestApp/uwsgi.ini

[uwsgi]
module = main
callable = app
master = true

Этот код определяет модуль, из которого будет обслуживаться приложение Flask. В данном случае это файл + main.py +, обозначаемый здесь как + main +. Опция + callable + указывает uWSGI использовать экземпляр + app +, экспортированный основным приложением. Опция + master + позволяет вашему приложению продолжать работу, поэтому при перезагрузке всего приложения остается мало времени простоя.

Затем создайте файл + main.py +, который является точкой входа в приложение. Точка входа инструктирует uWSGI о том, как взаимодействовать с приложением.

sudo nano main.py

Затем скопируйте и вставьте следующее в файл. Это импортирует экземпляр Flask с именем + app + из пакета приложения, который был ранее создан.

/var/www/TestApp/main.py

from app import app

Наконец, создайте файл + needs.txt +, чтобы указать зависимости, которые менеджер пакетов + pip + установит в ваше развертывание Docker:

sudo nano requirements.txt

Добавьте следующую строку, чтобы добавить Flask в качестве зависимости:

/var/www/TestApp/app/requirements.txt

Flask==1.0.2

Это указывает версию Flask, которая будет установлена. На момент написания этого руководства + 1.0.2 + является последней версией Flask. Вы можете проверить наличие обновлений на официальном веб-сайте Flask.

Сохраните и закройте файл. Вы успешно настроили приложение Flask и готовы установить Docker.

Шаг 2 - Настройка Docker

На этом шаге вы создадите два файла + Dockerfile + и + start.sh +, чтобы создать развертывание Docker. + Dockerfile + - это текстовый документ, который содержит команды, используемые для сборки изображения. Файл + start.sh + представляет собой сценарий оболочки, который создаст образ и создаст контейнер из + Dockerfile +.

Сначала создайте + Dockerfile.

sudo nano Dockerfile

Затем добавьте желаемую конфигурацию в + Dockerfile +. Эти команды определяют, как будет построен образ, и какие дополнительные требования будут включены.

/ Var / WWW / TestApp / Dockerfile

FROM tiangolo/uwsgi-nginx-flask:
RUN apk --update add bash nano
ENV STATIC_URL /static
ENV STATIC_PATH /var/www/app/static
COPY ./requirements.txt /var/www/requirements.txt
RUN pip install -r /var/www/requirements.txt

В этом примере образ Docker будет построен из существующего образа + tiangolo / uwsgi-nginx-flask +, который вы можете найти по адресу https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask [DockerHub]. Этот конкретный образ Docker является хорошим выбором среди других, поскольку он поддерживает широкий спектр версий Python и образов ОС.

Первые две строки указывают родительский образ, который вы будете использовать для запуска приложения и установки процессора команд bash и текстового редактора + nano +. Он также устанавливает клиент + git + для извлечения и передачи в службы управления версиями, такие как GitHub, GitLab и Bitbucket. + ENV STATIC_URL / static + - это переменная окружения, характерная для этого образа Docker. Он определяет статическую папку, из которой обслуживаются все ресурсы, такие как изображения, файлы CSS и файлы JavaScript.

Последние две строки копируют файл + needs.txt + в контейнер, чтобы его можно было выполнить, а затем анализируют файл + needs.txt + для установки указанных зависимостей.

Сохраните и закройте файл после добавления вашей конфигурации.

С вашим + Dockerfile + на месте вы почти готовы написать свой скрипт + start.sh +, который будет собирать контейнер Docker. Перед написанием скрипта + start.sh + сначала убедитесь, что у вас есть открытый порт для использования в конфигурации. Чтобы проверить, свободен ли порт, выполните следующую команду:

sudo nc localhost  < /dev/null; echo $?

Если вывод команды выше + 1 +, то порт свободен и пригоден для использования. В противном случае вам нужно будет выбрать другой порт для использования в вашем файле конфигурации + start.sh +.

Найдя открытый порт для использования, создайте скрипт + start.sh +:

sudo nano start.sh

Сценарий + start.sh + - это сценарий оболочки, который создаст образ из + Dockerfile + и создаст контейнер из получающегося образа Docker. Добавьте вашу конфигурацию в новый файл:

/var/www/TestApp/start.sh

#!/bin/bash
app=""
docker build -t ${app} .
docker run -d -p :80 \
 --name=${app} \
 -v $PWD:/app ${app}

Первая строка называется shebang. Он указывает, что это bash-файл, и он будет выполняться как команды. Следующая строка указывает имя, которое вы хотите дать изображению и контейнеру, и сохраняет его как переменную с именем + app +. Следующая строка указывает Docker создать образ из вашего + Dockerfile +, расположенного в текущем каталоге. Это создаст образ с именем + docker.test + в этом примере.

Последние три строки создают новый контейнер с именем + docker.test +, который открывается в порту + 56733 +. Наконец, он связывает текущий каталог с каталогом контейнера + + var / www + `.

Вы используете флаг + -d + для запуска контейнера в режиме демона или в качестве фонового процесса. Вы включаете флаг + -p +, чтобы привязать порт на сервере к определенному порту в контейнере Docker. В этом случае вы привязываете порт + 56733 + к порту + 80 + в контейнере Docker. Флаг + -v + указывает том Docker для монтирования в контейнере, и в этом случае вы монтируете весь каталог проекта в папку + / var / www + контейнера Docker.

Выполните скрипт + start.sh +, чтобы создать образ Docker и построить контейнер из полученного изображения:

sudo bash start.sh

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

sudo docker ps

Вы получите вывод, который показывает контейнеры:

OutputCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
58b05508f4dd        docker.test         "/entrypoint.sh /sta…"   12 seconds ago      Up 3 seconds       443/tcp, 0.0.0.0:56733->80/tcp   docker.test

Вы обнаружите, что контейнер + docker.test запущен. Теперь, когда он работает, перейдите по IP-адресу указанного порта в вашем браузере: + http: //: +

Вы увидите страницу, похожую на следующую:

изображение: https: //assets.digitalocean.com/articles/CART-62081/HelloWorld.png [домашняя страница]

На этом этапе вы успешно развернули приложение Flask в Docker. Далее вы будете использовать шаблоны для отображения контента пользователям.

Шаг 3 - Обслуживание файлов шаблонов

Templates - это файлы, которые отображают статический и динамический контент для пользователей, посещающих ваше приложение. На этом шаге вы создадите HTML-шаблон для создания домашней страницы приложения.

Начните с создания файла + home.html в каталоге` + app / templates`:

sudo nano app/templates/home.html

Добавьте код для вашего шаблона. Этот код создаст страницу HTML5, которая содержит заголовок и текст.

/var/www/TestApp/app/templates/home.html

<!doctype html>

<html lang="en-us">
 <head>
   <meta charset="utf-8">
   <meta http-equiv="x-ua-compatible" content="ie=edge">
   <title>Welcome home</title>
 </head>

 <body>
   <h1>Home Page</h1>
   <p>This is the home page of our application.</p>
 </body>
</html>

Сохраните и закройте файл после добавления шаблона.

Затем измените файл + app / views.py + для обслуживания вновь созданного файла:

sudo nano app/views.py

Сначала добавьте следующую строку в начало вашего файла, чтобы импортировать метод + render_template + из Flask. Этот метод анализирует файл HTML, чтобы отобразить веб-страницу для пользователя.

/var/www/TestApp/app/views.py

from flask import render_template
...

В конце файла вы также добавите новый маршрут для рендеринга файла шаблона. Этот код указывает, что пользователям предоставляется содержимое файла + home.html всякий раз, когда они посещают маршрут` + / template a` в вашем приложении.

/var/www/TestApp/app/views.py

...

@app.route('/template')
def template():
   return render_template('home.html')

Обновленный файл + app / views.py + будет выглядеть следующим образом:

/var/www/TestApp/app/views.py

from flask import render_template
from app import app

@app.route('/')
def home():
   return "Hello world!"

@app.route('/template')
def template():
   return render_template('home.html')

Сохраните и закройте файл, когда закончите.

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

sudo docker stop  && sudo docker start

Посетите ваше приложение по адресу + http: //: 56733 / template +, чтобы увидеть обслуживаемый новый шаблон.

Изображение: https: //assets.digitalocean.com/articles/CART-62081/HomePage.png домашнюю страницу []

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

Шаг 4 - Обновление приложения

Иногда вам нужно будет внести изменения в приложение, будь то установка новых требований, обновление контейнера Docker или изменения HTML и логики. В этом разделе вы настроите + touch-reload + для внесения этих изменений без перезапуска контейнера Docker.

Python autoreloading наблюдает за изменениями во всей файловой системе и обновляет приложение, когда обнаруживает изменение. Автоматическая загрузка не рекомендуется в производстве, поскольку она может очень быстро потреблять ресурсы. На этом шаге вы будете использовать + touch-reload + для отслеживания изменений в конкретном файле и перезагрузки при обновлении или замене файла.

Чтобы реализовать это, начните с открытия файла + uwsgi.ini +:

sudo nano uwsgi.ini

Затем добавьте выделенную строку в конец файла:

/var/www/TestApp/uwsgi.ini

module = main
callable = app
master = true

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

Чтобы продемонстрировать это, внесите небольшое изменение в свое приложение. Начните с открытия файла + app / views.py +:

sudo nano app/views.py

Замените строку, возвращаемую функцией + home +:

/var/www/TestApp/app/views.py

from flask import render_template
from app import app

@app.route('/')
def home():
   return ""

@app.route('/template')
def template():
   return render_template('home.html')

Сохраните и закройте файл после внесения изменений.

Затем, если вы откроете домашнюю страницу своего приложения по адресу + http: //: +, вы заметите, что изменения не отражаются. Это потому, что условием для перезагрузки является изменение файла + uwsgi.ini +. Чтобы перезагрузить приложение, используйте + touch + для активации условия:

sudo touch uwsgi.ini

Перезагрузите домашнюю страницу приложения в вашем браузере снова. Вы обнаружите, что приложение включило изменения:

изображение: https: //assets.digitalocean.com/articles/CART-62081/ThereHasBeenAChange.png [Обновление домашней страницы]

На этом шаге вы устанавливаете условие + touch-reload + для обновления приложения после внесения изменений.

Заключение

В этом руководстве вы создали и развернули приложение Flask в контейнере Docker. Вы также сконфигурировали + touch-reload + для обновления приложения без необходимости перезапуска контейнера.

С новым приложением в Docker вы теперь можете легко масштабировать. Чтобы узнать больше об использовании Docker, ознакомьтесь с их official документацией.

Related