Как создать и развернуть приложение Flask с помощью Docker в Ubuntu 18.04
Автор выбрал программу Write for DOnations.
Введение
Docker — это приложение с открытым исходным кодом, которое позволяет администраторам создавать, управлять, развертывать и реплицировать приложения с помощью контейнеров. Контейнеры можно рассматривать как пакеты, содержащие зависимости, необходимые приложению для работы на уровне операционной системы. Это означает, что каждое приложение, развернутое с помощью Docker, живет в собственной среде, и его требования обрабатываются отдельно.
Питон. Он называется микрофреймворком, потому что для его запуска не требуются специальные инструменты или плагины. Фреймворк Flask легкий и гибкий, но хорошо структурированный, что делает его предпочтительным по сравнению с другими фреймворками.
Развертывание приложения Flask с помощью Docker позволит вам реплицировать приложение на разных серверах с минимальной реконфигурацией.
В этом руководстве вы создадите приложение Flask и развернете его с помощью Docker. В этом руководстве также рассказывается, как обновить приложение после развертывания.
Предпосылки
Чтобы следовать этому руководству, вам понадобится следующее:
- Пользователь без полномочий root с привилегиями sudo, настроенными в соответствии с руководством Initial Server Setup with Ubuntu 18.04.
- Один сервер Ubuntu 18.04 с установленным Docker, настроенный с помощью образа Docker, доступного в один клик.
- Руководство по установке Nginx в Ubuntu 18.04.
Шаг 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, такие как его представления и чертежи. Схемы создают компоненты приложения и поддерживают общие шаблоны в приложении или в нескольких приложениях.
В каталоге static
хранятся такие ресурсы, как изображения, файлы CSS и JavaScript. Каталог templates
— это место, где вы будете размещать шаблоны HTML для своего проекта.
Теперь, когда структура базовой папки завершена, создайте файлы, необходимые для запуска приложения Flask. Сначала создайте файл __init__.py
в каталоге app
. Этот файл сообщает интерпретатору Python, что каталог app
является пакетом и должен рассматриваться как таковой.
Выполните следующую команду, чтобы создать файл:
- sudo nano app/__init__.py
Пакеты в Python позволяют группировать модули в логические пространства имен или иерархии. Такой подход позволяет разбить код на отдельные и управляемые блоки, выполняющие определенные функции.
Далее вы добавите код в __init__.py
, который создаст экземпляр Flask и импортирует логику из файла views.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!
пользователям, которые посещают вашу веб-страницу:
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:
[uwsgi]
module = main
callable = app
master = true
Этот код определяет модуль, из которого будет обслуживаться приложение Flask. В данном случае это файл main.py
, обозначенный здесь как main
. Параметр callable
указывает uWSGI использовать экземпляр app
, экспортированный основным приложением. Параметр master
позволяет вашему приложению продолжать работать, поэтому время простоя будет минимальным даже при перезагрузке всего приложения.
Затем создайте файл main.py
, который является точкой входа в приложение. Точка входа указывает uWSGI, как взаимодействовать с приложением.
- sudo nano main.py
Затем скопируйте и вставьте следующее в файл. Это импортирует экземпляр Flask с именем app
из ранее созданного пакета приложения.
from app import app
Наконец, создайте файл requirements.txt
, чтобы указать зависимости, которые менеджер пакетов pip
установит в ваше развертывание Docker:
- sudo nano requirements.txt
Добавьте следующую строку, чтобы добавить Flask в качестве зависимости:
Flask==1.0.2
Это указывает версию Flask для установки. На момент написания этого руководства последней версией Flask была 1.0.2
. Вы можете проверить наличие обновлений на официальном сайте Flask.
Сохраните и закройте файл. Вы успешно настроили приложение Flask и готовы настроить Docker.
Шаг 2 — Настройка Докера
На этом шаге вы создадите два файла, Dockerfile
и start.sh
, для развертывания Docker. Dockerfile
– это текстовый документ, содержащий команды, используемые для сборки образа. Файл start.sh
— это сценарий оболочки, который создаст образ и создаст контейнер из Dockerfile
.
Сначала создайте Dockerfile
.
- sudo nano Dockerfile
Затем добавьте нужную конфигурацию в 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 и образов ОС.
Первые две строки определяют родительский образ, который вы будете использовать для запуска приложения и установки командного процессора 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. Добавьте свою конфигурацию в новый файл:
#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
--name=${app} \
-v $PWD:/app ${app}
Первая строка называется шебанг. Он указывает, что это 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://ip-address:56733
Вы увидите страницу, похожую на следующую:
На этом шаге вы успешно развернули приложение Flask в Docker. Далее вы будете использовать шаблоны для отображения контента пользователям.
Шаг 3 — Обслуживание файлов шаблонов
Шаблоны — это файлы, которые отображают статическое и динамическое содержимое для пользователей, посещающих ваше приложение. На этом шаге вы создадите HTML-шаблон для создания домашней страницы приложения.
Начните с создания файла home.html
в каталоге app/templates
:
- sudo nano app/templates/home.html
Добавьте код вашего шаблона. Этот код создаст страницу HTML5, содержащую заголовок и некоторый текст.
<!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, чтобы отобразить веб-страницу для пользователя.
from flask import render_template
...
В конце файла вы также добавите новый маршрут для рендеринга файла шаблона. Этот код указывает, что пользователям предоставляется содержимое файла home.html
всякий раз, когда они посещают маршрут /template
в вашем приложении.
...
@app.route('/template')
def template():
return render_template('home.html')
Обновленный файл 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://ваш-IP-адрес:56733/template
, чтобы увидеть, как обслуживается новый шаблон.
Здесь вы создали файл шаблона Docker для обслуживания посетителей вашего приложения. На следующем шаге вы увидите, как изменения, которые вы вносите в свое приложение, могут вступить в силу без перезапуска контейнера Docker.
Шаг 4 — Обновление приложения
Иногда вам потребуется внести изменения в приложение, будь то установка новых требований, обновление контейнера Docker или изменение HTML и логики. В этом разделе вы настроите touch-reload
для внесения этих изменений без перезапуска контейнера Docker.
Автоперезагрузка в Python отслеживает изменения во всей файловой системе и обновляет приложение при обнаружении изменений. Автоматическая перезагрузка не рекомендуется в производственной среде, поскольку она может очень быстро стать ресурсоемкой. На этом шаге вы будете использовать touch-reload
для отслеживания изменений в конкретном файле и перезагрузки при обновлении или замене файла.
Чтобы реализовать это, начните с открытия файла uwsgi.ini
:
- sudo nano uwsgi.ini
Затем добавьте выделенную строку в конец файла:
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini
Это указывает файл, который будет изменен, чтобы вызвать перезагрузку всего приложения. После внесения изменений сохраните и закройте файл.
Чтобы продемонстрировать это, внесите небольшое изменение в свое приложение. Начните с открытия файла app/views.py
:
- sudo nano app/views.py
Замените строку, возвращаемую функцией home
:
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, ознакомьтесь с их официальной документацией.