Tutorial

Создание и развертывание приложения Flask с использованием Docker в Ubuntu 18.04

NginxDockerUbuntu 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

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

  • cd /var/www/TestApp

Создайте базовую структуру папок для приложения 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 над функцией называется декоратором. Декораторы изменяют функцию, которая следует за ними. В данном случае декторатор указывает Flask, какой URL активирует функцию home(). Текст hello world, возвращаемый функцией home, будет отображаться пользователю в браузере.

Создав файл views.py, вы готовы к созданию файла uwsgi.ini. Этот файл будет содержать конфигурации 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

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

  • sudo nano requirements.txt

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

/var/www/TestApp/app/requirements.txt
Flask==1.0.2

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

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

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

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

Вначале создайте файл Dockerfile.

  • sudo nano Dockerfile

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

/var/www/TestApp/Dockerfile
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
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, который можно найти на ресурсе DockerHub. Этот конкретный образ Docker лучше многих других, потому что он поддерживает широкий спектр версий Python и образов ОСs.

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

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

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

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

  • sudo nc localhost 56733 < /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.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
  --name=${app} \
  -v $PWD:/app ${app}

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

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

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

Запустите скрипт start.sh для создания образа Docker и построения контейнера на основе этого образа:

  • sudo bash start.sh

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

  • sudo docker ps

В результате будет выведен список контейнеров:

Output
CONTAINER 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://ip-address:56733

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

Главная страница

На этом шаге вы успешно развернули свое приложение Flask в контейнере Docker. Теперь вы используете шаблоны, чтобы показать пользователям контент.

Шаг 3 — Работа с файлами шаблонов

Шаблоны — это файлы, показывающие статичный и динамический контент пользователям вашего приложения. На этом шаге вы создадите шаблон 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 в вашем приложении.

/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 docker.test && sudo docker start docker.test

Откройте свое приложение по адресу http://your-ip-address:56733/template, чтобы увидеть, как выводится новый шаблон.

главная страница

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

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

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

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

Для реализации этой функции откройте файл uwsgi.ini:

  • sudo nano uwsgi.ini

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

/var/www/TestApp/uwsgi.ini
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini

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

Чтобы продемонстрировать это, внесите в ваше приложение небольшое изменение. Для начала откройте файл 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 "<b>There has been a change</b>"

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

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

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

  • sudo touch uwsgi.ini

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

Главная страница обновлена

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

Заключение

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

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

0 Comments

Creative Commons License