Введение
Docker — это платформа контейнеризации с открытым исходным кодом. Это легкая, виртуализированная, портативная, программно-определяемая стандартизированная среда, которая позволяет программному обеспечению работать изолированно от другого ПО, запущенного на физическом хосте. Docker предлагает легкую альтернативу виртуальным машинам. В то же время он обеспечивает портативность, производительность, гибкость и масштабируемость приложений. Для получения подробного руководства по экосистеме Docker ознакомьтесь с нашим подробным обзором контейнеризации с помощью Docker.
Flask — это минималистичный веб-фреймворк с открытым исходным кодом, созданный на Python. Среди отличных особенностей Flask — его легкость, гибкость и высокая структурированность. Кроме того, для его работы не требуются какие-либо специальные инструменты или плагины.
Сочетание Flask и Docker дает вам легкое, гибкое и масштабируемое приложение. Вы можете развернуть его на множестве серверов и инфраструктур благодаря портативности контейнеров Docker. Цель этого руководства — показать вам, как развернуть приложение Flask с помощью Docker. Мы также продемонстрируем, как сделать так, чтобы будущие обновления вашего приложения вступали в силу.
Предварительные требования
Это практическое руководство, и вам необходимо создать среду, которая позволит вам следовать инструкциям:
- У вас должна быть установлена Ubuntu 20.04 в качестве исходной операционной среды. Вам также необходимо создать пользователя без прав root с привилегиями sudo.
- Кроме того, вам необходимо установить Docker. У нас есть руководство по установке и работе с Docker в Ubuntu. Выполните шаги 1, 2, 3 и 4. Это должно работать для любого дистрибутива Ubuntu.
- Наконец, вам необходимо установить Nginx. Следуйте нашему руководству по установке Nginx в Ubuntu.
Теперь давайте начнем!
Шаг 1. Подготовка приложения Flask
Мы начнем с создания каталога, в котором будет храниться наше приложение Flask. Вы можете выбрать любое имя каталога по своему усмотрению. Однако для этого руководства мы назовем его flask_demo. Мы сохраним файлы проекта внутри каталога /var/www, который обычно является каталогом, к которому Ubuntu по умолчанию разрешает доступ из публичного интернета. Сначала выполните следующие команды, чтобы создать каталог и перейти в него:
|
1 2 3 |
sudo mkdir /var/www/flask_demo cd /var/www/flask_demo |
Внутри этого корневого каталога нашего проекта мы создадим базовую структуру папок приложения Flask. Затем выполните следующую команду для создания базовой структуры, добавив флаг -p, чтобы попутно создать все родительские папки:
|
1 |
sudo mkdir -p app/static app/templates |
Папка app содержит все файлы, связанные с приложением Flask, включая views и blueprints. Views содержат код, который вы пишете для ответа на запросы, поступающие в ваше приложение. Blueprints помогают создавать компоненты приложения и поддерживают общие шаблоны в приложениях Flask.
Папка с говорящим названием static хранит статические ресурсы, такие как изображения, файлы CSS и JavaScript. Каталог templates содержит все HTML-шаблоны для проекта.
Теперь мы можем начать писать файлы, необходимые для инициализации приложения Flask. Начните с создания файла с именем __init__.py внутри каталога app, чтобы сообщить Python интерпретатору, что каталог app следует рассматривать как пакет. Выполните следующую команду в терминале, чтобы открыть файл в редакторе nano:
|
1 |
sudo nano app/__init__.py |
Мы используем пакеты в Python для группировки модулей в логические пространства имен или иерархии. Модульность позволяет разбивать код на отдельные управляемые блоки, выполняющие определенные функции.
После этого внутри файла __init__.py, открытого в вашем редакторе, добавьте следующий фрагмент кода, чтобы запустить экземпляр Flask и импортировать логику из views.py, который вы создадите на следующих шагах:
|
1 2 3 4 5 |
from flask import Flask app = Flask(__name__) from app import views |
Когда закончите, нажмите Ctrl + O и ENTER, чтобы сохранить файл, а затем закройте его с помощью Ctrl + X. Далее давайте создадим views.py внутри директории app . Файл views.py будет содержать большую часть логики приложения:
|
1 |
sudo nano app/views.py |
Добавьте в файл следующий фрагмент кода. Этот код будет выводить простую строку, показывающую, что ваше приложение работает, когда пользователи посещают ваш сайт:
|
1 2 3 4 5 |
from app import app @app.route('/') def home(): return "Наше приложение Flask работает!" |
В этом файле мы начнем с импорта экземпляра приложения Flask. Затем нам нужно добавить строку для определения маршрута: @app.route(/). Строка @app.route(/) называется декоратором в Flask. Вы можете использовать декораторы для добавления дополнительных функций в одну или несколько функций. В данном случае мы передаем вызов маршрута / функции home. Когда пользователь перейдет по этому маршруту, он увидит текст: "Наше приложение Flask работает!".
Далее вы создадите файл uwsgi.ini, содержащий конфигурации uWSGI для приложения. uWSGI — это вариант развертывания для Nginx, который служит протоколом и сервером приложений. Выполните следующую команду, чтобы создать файл в корневом каталоге проекта с помощью редактора nano:
|
1 |
sudo nano uwsgi.ini |
В открывшийся файл добавьте следующий фрагмент кода:
|
1 2 3 4 |
[uwsgi] module = main callable = app master = true |
Этот файл содержит несколько директив. Ниже мы определим их назначение:
- module – определяет модуль, из которого будет запускаться приложение Flask. Мы установили модуль как main, ссылаясь на файл main.py в корневом каталоге. Мы создадим этот файл на следующем шаге.
- callable – указывает uWSGI использовать экземпляр app , экспортированный из приложения.
- master – гарантирует, что приложение продолжит работу, чтобы минимизировать время простоя при перезагрузке всего приложения.
Сохраните и закройте файл, когда закончите.
Теперь вы можете создать файл main.py, чтобы определить точку входа в ваше приложение. uWSGI будет читать этот файл, чтобы знать, как взаимодействовать с приложением. Выполните следующую команду, чтобы создать файл main.py с помощью nano внутри корневой директории вашего проекта:
|
1 |
sudo nano main.py |
Добавьте в файл следующую строку, которая импортирует экземпляр Flask, созданный в пакете приложения:
|
1 |
from app import app |
Последнее, что вы сделаете на этом шаге, — это определите зависимости, необходимые для работы приложения. Мы определим эти зависимости внутри файла под названием dependencies.txt. Когда Docker собирает образ вашего приложения, он выполняет команду пакетного менеджера pip (пакетного менеджера) для установки зависимостей. Откройте файл в корневом каталоге с помощью следующей команды:
|
1 |
sudo nano dependencies.txt |
До этого момента в нашем проекте нам нужна только одна зависимость: Flask. Следовательно, мы можем добавить следующую строку, чтобы указать нужную версию Flask для нашего проекта:
|
1 |
Flask==2.0.1 |
Мы остановимся на Flask версии 2.0.1 в качестве зависимости. Это последняя версия на момент написания этого руководства. Вы можете узнать больше о различных версиях на странице Flask Changes. На этом настройка приложения Flask завершена. Теперь давайте подготовим конфигурации Docker для развертывания.
Шаг 2. Настройка Docker
Чтобы настроить развертывание Docker, мы создадим два файла: Dockerfile и start.sh. Файл Dockerfile содержит декларативные строки, из которых состоит образ Docker. Файл start.sh представляет собой простой скрипт оболочки для сборки образа и запуска контейнера из Dockerfile. Находясь в корневом каталоге проекта, выполните следующую команду, чтобы создать Dockerfile:
|
1 |
sudo nano Dockerfile |
Этот файл содержит необходимые конфигурации для образа Docker. Далее добавьте следующий фрагмент кода, чтобы указать зависимости и способ сборки образа:
|
1 2 3 4 5 6 7 8 9 10 11 |
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 RUN apk --update add bash nano git ENV STATIC_URL /static ENV STATIC_PATH /var/www/app/static COPY ./dependencies.txt /var/www/dependencies.txt RUN pip install -r /var/www/dependencies.txt |
Первая строка в Dockerfile определяет базовый образ, на основе которого мы создаем наш образ. В данном случае мы будем строить его на основе tiangolo/uwsgi-nginx-flask, доступного на DockerHub. Мы выбрали именно этот образ, так как он поддерживает множество версий Python.
Мы также указываем, что хотим обновить образ. Затем нам нужно добавить bash командный процессор , nano текстовый редактор, и git клиент для получения и отправки исходного кода из репозиториев контроля версий, таких как GitHub, Bitbucket, или Gitlab. Строки с ENV задают переменные окружения, которые будут использоваться в контейнере.
Команда COPY копирует зависимости в контейнер. Команда RUN вызывает pip пакетный менеджер для разбора файла dependencies.txt и установки зависимостей. Сохраните и закройте файл после завершения редактирования.
Далее вы создадите скрипт start.sh. Этот скрипт будет содержать команды Docker для сборки и запуска образа. Хотя вы можете выполнять эти команды последовательно в терминале, мы подумали, что чище добавить их в шелл-скрипт и просто вызывать его из терминала одной командой.
Прежде чем определить содержимое этого файла, мы должны сначала найти свободный порт, который не используется другими службами. Мы будем использовать порт 45644. Однако вы можете выбрать другой порт. Выполните следующую строку, чтобы проверить, свободен ли порт:
|
1 |
sudo nc localhost 45644 < /dev/null; echo $? |
В зависимости от выбранного вами порта, если вывод вышеуказанной команды равен 1, значит, он свободен. В противном случае вам придется выбрать другой порт и повторить команду:

Поскольку мы определили свободный порт, теперь мы можем создать файл с помощью nano в корневом каталоге проекта, выполнив следующую команду:
|
1 |
sudo nano start.sh |
Добавьте в этот файл следующий фрагмент кода:
|
1 2 3 4 5 6 7 |
#!/bin/bash app_name="docker-flask-demo" docker build -t ${app_name} . docker run -d -p 45644:80 --name=${app_name} -v $PWD:/app ${app_name} |
Первая строка, называемая shebang, указывает, что это файл bash и должен выполняться как набор команд. Вторая строка объявляет переменную с именем app_name. Мы используем эту переменную для задания имен образа и контейнера. Третья строка указывает Docker собрать образ на основе определения Dockerfile в текущем каталоге. Образ будет называться docker-flask-demo в соответствии с переменной.
Последняя строка создает контейнер с именем docker-flask-demo в соответствии с определенной нами переменной. Флаг -d оставляет контейнер работать в фоновом режиме (в фоновом состоянии) после завершения выполнения команды. Флаг -p связывает порт на сервере с определенным портом в контейнере. В данном случае мы привязываем порт 45644 на хост-машине к порту 80, который Docker откроет в контейнере.
Мы используем флаг -v для указания тома Docker для монтирования в контейнер. Переменная $PWD — это стандартная переменная Linux, которая содержит путь к текущему каталогу, в котором вы находитесь в данный момент:

В нашем случае мы монтируем весь каталог проекта в каталог /var/www контейнера. Конфигурация Docker готова. Вы можете собрать образ и запустить контейнер на основе собранного образа, выполнив следующую команду:
|
1 |
sudo bash start.sh |
Дождитесь завершения работы скрипта, затем выполните следующую команду Docker, чтобы вывести список всех запущенных контейнеров:
|
1 |
sudo docker ps |
Вывод отобразит запущенные контейнеры:

Вы должны увидеть наш контейнер с именем docker-flask-demo в списке запущенных контейнеров. Найдите публичный IP вашего сервера и перейдите по нему в браузере на указанный порт: http://your-server-public-ip:45644.
Вы должны увидеть похожий вывод:

Если вы видите это в своем браузере, значит, вы успешно развернули приложение Flask. Далее мы будем изменять файлы и отдавать контент пользователям с помощью шаблонов.
Шаг 3. Отдача контента через файлы шаблонов
В Flask Шаблоны используются для отображения статического и динамического контента посетителям сайта. Мы покажем вам, как создать HTML шаблон и отдавать его пользователям, когда они переходят по определенному маршруту. Например, это может быть главная страница или страница «О проекте».
Выполните следующую команду в терминале, чтобы создать файл index.html в директории app/templates :
|
1 |
sudo nano app/templates/index.html |
Затем добавьте в файл следующий фрагмент кода:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Flask Demo</title> </head> <body> <h2>Вы на главной</h2> <p>Добро пожаловать на демо-страницу Flask с DockerPage</p> </body> </html> |
Сохраните и закройте файл, когда закончите. Также создайте еще одну страницу, назовем ее страницей «О проекте», с помощью следующей команды:
|
1 |
sudo nano app/templates/about.html |
Добавьте в файл следующий фрагмент кода:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>О компании Flask Demo</title> </head> <body> <h2>О проекте</h2> <p>Это был демонстрационный проект. Он . показывает, как создать Flask- приложение с Docker и NginxDocker and Nginx.</p> <p>Вы можете добавлять сколько угодно страниц и файловas you like</p> </body> </html> |
Сохраните и закройте файл, когда закончите. Далее измените файл app/views.py , чтобы сослаться на шаблоны, а также на маршруты для самих страниц:
|
1 |
sudo nano app/views.py |
Измените файл так, чтобы он выглядел следующим образом:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "Наше приложение Flask работает!" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Сохраните и закройте файл, когда закончите. Внесенные вами изменения не вступят в силу, пока вы не остановите и не перезапустите контейнер. Выполните следующие команды Docker, чтобы остановить и запустить контейнер. Обратите внимание на имя контейнера, которое мы определили ранее:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Как только контейнер запустится и заработает, перейдите на Главную страницу и страницу «О нас», чтобы увидеть новый контент:
|
1 |
Главная страница: http://your-server-public-ip:45644/index |

|
1 |
О нас страница: http://your-server-public-ip:45644/about |

Итак, вы создали приложение Flask, которое может отдавать контент посетителям вашего сайта. Вот структура файлов проекта:

Вы, вероятно, заметили, что нам пришлось перезапустить контейнер Docker, чтобы он применил новые изменения. На следующем шаге мы автоматизируем этот процесс, чтобы сократить время простоя.
Шаг 4. Настройка автоматической перезагрузки при обновлении файлов приложения
Время от времени мы вносим изменения в приложение, чтобы улучшить логику, пользовательский интерфейс или добавить зависимости. Чтобы такие изменения вступили в силу, может потребоваться перезапуск контейнера Docker. К счастью, uWSGI имеет функцию под названием touch-reload для перезагрузки скрипта Python без перезапуска контейнера.
Из коробки Python имеет функцию auto-reloading (автоматической перезагрузки), которая отслеживает изменения во всей файловой системе и обновляет приложение при их обнаружении. Хотя автоперезагрузка полезна для минимизации времени простоя, она может быть ресурсоемкой. Поэтому она не рекомендуется для продакшн-сред.
Давайте посмотрим, как можно использовать touch-reload для отслеживания изменений в конкретном файле и перезагрузки приложения при их наличии. Измените файл uwsgi.ini с помощью редактора nano:
|
1 |
sudo nano uwsgi.ini |
Добавьте выделенную строку, чтобы файл выглядел следующим образом:
|
1 2 3 4 5 |
[uwsgi] module = main callable = app master = true touch-reload = /app/uwsgi.ini |
Сохраните и закройте файл, когда закончите. Добавленная строка указывает файл, изменение которого приведет к перезагрузке приложения. Однако, чтобы это условие активировалось для будущих изменений, сначала необходимо перезапустить контейнер:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Теперь вы можете изменить файл app/views.py чтобы продемонстрировать работу автоперезагрузки:
|
1 |
sudo nano app/views.py |
Измените строку, возвращаемую функцией home, как показано на выделенном фрагменте:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "<h3>Some changes to Our Flask application to auto reload!</h3>" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Сохраните и закройте файл после завершения.
Откройте главную страницу вашего приложения в браузере: http://your-server-public-ip:45644.
Вы пока не увидите никаких изменений. Это связано с тем, что условие touch-reload обнаруживает изменения в файле uwsgi.ini . Вы можете использовать команду touch для активации этого условия, тем самым перезагрузив все приложение с помощью следующей команды:
|
1 |
sudo touch uwsgi.ini |
Теперь, если вы обновите главную страницу, вы увидите новые изменения:

В дальнейшем, если вы внесете какие-либо изменения, вам нужно будет только запустить команду sudo touch uwsgi.ini и все приложение перезапустится с меньшим временем простоя. На этом мы подходим к концу этого руководства.
Заключение
В этом руководстве вы реализовали и развернули приложение Flask с помощью образов и контейнеров Docker. Чтобы свести к минимуму время простоя, избегая необходимости перезапуска контейнера, вы настроили touch-reload для отслеживания изменений в конкретном файле и автоматической перезагрузки всего приложения. В завершение вы протестировали все это в браузере, чтобы убедиться в его работоспособности.
Docker обеспечивает более быстрое развертывание и позволяет легко масштабировать приложения. Если вы хотите узнать больше о различных командах Docker, пожалуйста, ознакомьтесь с этим руководством по установке и использованию Docker на Ubuntu.
Дополнительные ресурсы по Docker в нашем блоге, вы можете ознакомиться со следующим:
- Технология контейнеризации: типы и использование различных контейнеров на PaaS-платформе CloudSigma
- Как обмениваться данными между контейнером Docker и хостом
- Установка и настройка Docker на CentOS 7
- Развертывание Laravel, Nginx и MySQL с помощью Docker Compose
- Очистка ресурсов Docker — образов, контейнеров и томов
Приятной работы!
Комментарии
Комментариев пока нет. Будьте первым.