angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Запуск нескольких (Flask) сайтов с одной установкой Docker

Разделяя код и (опционально) шаблоны, мы избегаем копирования и сокращаем время обслуживания.

30 сентября 2020
post main image
https://unsplash.com/@windows

Я разработал один сайт Flask на Docker , но через некоторое время, когда мой код стал более стабильным, я захотел использовать такую же установку для других сайтов. Для одного сайта я сделал копию, потому что он должен был работать вчера. Но на самом деле я хотел поделиться всем кодом и некоторыми шаблонами. Конечно, каждый сайт имеет свой собственный статический каталог, каталог логов, шаблоны и т.д. Основная причина для обмена заключается в том, что код все еще находится в тяжелой разработке, и я не хочу поддерживать несколько копий одного и того же кода.

Расширение моего скрипта для сборки и запуска Docker

Я написал интерактивный сценарий, который я использую для сборки Docker image и запуска контейнера Docker с соответствующей версией. С их помощью я могу запускать разработку, тестирование и staginglocal, и staging , а производственные, контейнеры даже параллельные. Я просто открываю другое окно терминала и запускаю свой стартовый скрипт Docker . Мне пришлось использовать этот скрипт для поддержки нескольких сайтов. В главном каталоге есть два подкаталога:

  • docker-templates
  • docker-versions

Docker-templates содержит шаблоны Docker-compose при создании новой версии для сайта. Версия всегда означает новый набор файлов docker-compose и файл с переменными окружения. Кроме того, для staging и производственной версии, она также будет содержать (tarred) Docker image и, опционально, статический дамп каталога и базы данных.

Сценарий Docker собирает файлы из соответствующей директории docker-templates , генерирует новый номер версии, исправляет новый номер версии в файлах, создает директорию новой версии в docker-versions и помещает файлы туда. Эта установка позволяет мне вносить изменения в Docker-compose и файлы окружения в docker-templates. Новые версии включают последние изменения, а старые версии остаются неизменными. Для разработки и тестирования все файлы приложения находятся вне контейнера, что означает, что генерация нового образа необходима только при добавлении или удалении пакетов (requirements.txt). Новая структура каталогов:

.
|--  docker-templates
|   `-- sites
|       |--  peterspython
|       |   |--  docker-compose_development.yml
|       |   |--  docker-compose_production.yml
|       |   |--  docker-compose_shared.yml
|       |   |--  docker-compose_staginglocal.yml
|       |   |--  docker-compose_staging.yml
|       |   |--  docker-compose_testing.yml
|       |   |-- env_development
|       |   |-- env_production
|       |   |-- env_staging
|       |   |-- env_staginglocal
|       |   `-- env_testing
|       `-- anothersite
|           |--  docker-compose_development.yml
|           |--  docker-compose_production.yml
|           |--  docker-compose_shared.yml
|           |--  docker-compose_staginglocal.yml
|           |--  docker-compose_staging.yml
|           |--  docker-compose_testing.yml
|           |-- env_development
|           |-- env_production
|           |-- env_staging
|           |-- env_staginglocal
|           `-- env_testing
|--  docker-versions
|   `-- sites
|       |--  peterspython
|       |   |-- 1.821_development
|       |   |   |-- deployment.env
|       |   |   |--  docker-compose_deployment.yml
|       |   |   `--  docker-compose_shared.yml
|       |   |   ...
|       |   |-- 1.829_production
|       |   |   |-- deployment.env
|       |   |   |--  docker-compose_deployment.yml
|       |   |   |--  docker-compose_shared.yml
|       |   |   `--  peterspython_web_production_image_1.829.tar
|       `-- anothersite
|           |-- 1.778_development
|           |   |-- deployment.env
|           |   |--  docker-compose_deployment.yml
|           |   `--  docker-compose_shared.yml
|           `-- 1.779_development
|               |-- deployment.env
|               |--  docker-compose_deployment.yml
|               `--  docker-compose_shared.yml
|-- project

Стартовый скрипт Docker позволяет мне выбрать веб-сайт (peterspython, anothersite), а затем представляет мне меню всех версий. Когда я выбираю версию, мне представляется меню со списком действий, таких как запуск контейнера, выполнение в контейнер и т.д. Перед началом действия стартовый скрипт Docker копирует файлы из каталога docker-версии в основной каталог так, чтобы у нас всегда были файлы в том же месте, как если бы мы запускали один сайт.

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

Расширение структуры каталога проекта

Я хотел поделиться всем кодом между сайтами, но хотел, чтобы у них были свои собственные шаблоны, статический каталог, лог-файлы и т.д. Новая структура каталогов проекта:

.
|-- app
|   |--  blueprints
|   |-- factory.py
|   |-- services.py
|   `-- templates
|-- sites
|   |--  peterspython
|   |   |--  docker-volumes
|   |   |-- static
|   |   |-- stylesheets
|   |   `-- templates
|   `-- anothersite
|       |--  docker-volumes
|       |-- static
|       |-- stylesheets
|       `-- templates
|
|-- app_run.py
|--  Dockerfile
|

Код в приложении является общим. Docker-volumes - это монтирование тома для лог-файлов и т.д. Отличием от односайтовой установки является расположение файла конфигурации Flask config.py. Я загружаю этот файл в create_app() с помощью метода from_object(). Чтобы убедиться, что файл может быть найден, я добавляю директорию файла, указанную переменными окружения Docker , в sys.path:

def  create_app(deploy_config):
    ...
    # to find config.py
    sys.path.insert(0, project_docker_volume_config_dir)

	# load config
    app.config.from_object(all_configs[deploy_config])

Другое отличие от единой настройки сайта - это шаблоны. Я хочу, чтобы он работал следующим образом. Когда каталог сайта не содержит шаблона, то он возвращается в каталог шаблонов приложений. Очень легко сказать Jinja , где искать шаблоны. Jinja поддерживает множество загрузчиков, я выбрал ChoiceLoader:

from jinja2 import (
    ChoiceLoader,
)

def  create_app(deploy_config):
    ...
    # set template paths
    template_loader = ChoiceLoader([
        # site templates
        app.jinja_loader,
        # default templates
        FileSystemLoader('/home/flask/project/app/templates')
    ])
    app.jinja_loader = template_loader
    ...

Заключение

Здесь я представил способ, как поделиться кодом и (опционально) шаблонами между несколькими сайтами, не делая копию всего дерева каталогов для нового сайта. Хотя есть много вещей, которые можно улучшить, я использую этот способ и счастлив, что на это уделил время.

Ссылки / кредиты

API
https://jinja.palletsprojects.com/en/2.11.x/api/

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.