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

Ausführen mehrerer (Flask) Websites mit einer einzigen Docker -Einrichtung

Durch die gemeinsame Nutzung des Codes und (optional) der Vorlagen vermeiden wir das Anfertigen von Kopien und reduzieren den Wartungsaufwand.

30 September 2020
post main image
https://unsplash.com/@windows

Ich habe eine Website Flask auf Docker entwickelt, aber nach einiger Zeit, als mein Code stabiler wurde, wollte ich dasselbe Setup auch für andere Websites verwenden. Für eine Website habe ich eine Kopie gemacht, weil sie gestern funktionieren musste. Aber was ich wirklich wollte, war, den gesamten Code und einige der Vorlagen weiterzugeben. Natürlich hat jede Website ihr eigenes statisches Verzeichnis, Logging-Verzeichnis, Vorlagen usw. Der Hauptgrund für die gemeinsame Nutzung ist, dass der Code noch stark weiterentwickelt wird und ich nicht mehrere Kopien desselben Codes pflegen möchte.

Erweiterung meines Docker -Build- und Startskripts

Ich habe ein interaktives Skript geschrieben, das ich zum Erstellen der Docker images und zum Starten des Containers Docker mit der richtigen Version verwende. Mit diesen kann ich die Entwicklung, das Testen und die Container staginglocal und staging und Produktion, sogar parallel laufen lassen. Ich öffne einfach ein weiteres Terminalfenster und lasse mein Startskript Docker laufen. Ich musste dieses Skript verwenden, um mehrere Websites zu unterstützen. Im Hauptverzeichnis gibt es zwei Unterverzeichnisse:

  • docker-templates
  • docker-versions

Docker-templates enthält die Vorlagen Docker-compose , wenn eine neue Version für eine Website erstellt wird. Eine Version bedeutet immer einen neuen Satz von docker-compose -Dateien und eine Datei mit Umgebungsvariablen. Darüber hinaus enthält sie für staging und Produktion auch ein (geteertes) Docker image und optional ein statisches Verzeichnis und einen Datenbank-Dump.

Das Build-Skript Docker nimmt die Dateien aus dem richtigen docker-templates -Verzeichnis, generiert eine neue Versionsnummer, patcht die neue Versionsnummer in den Dateien, erstellt das neue Versionsverzeichnis in docker-versions und legt die Dateien dort ab. Diese Einrichtung ermöglicht es mir, Änderungen an Docker-compose und Umgebungsdateien in docker-templates vorzunehmen. Neue Versionen enthalten die neuesten Änderungen und ältere Versionen bleiben unverändert. Für die Entwicklung und das Testen befinden sich alle Anwendungsdateien außerhalb des Containers, so dass die Erzeugung eines neuen Images nur beim Hinzufügen oder Entfernen von Paketen (requirements.txt) erforderlich ist. Die neue Verzeichnisstruktur:

.
|--  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

Das Startskript Docker erlaubt mir die Auswahl einer Website (peterspython, eine andere Website) und zeigt mir dann ein Menü aller Versionen an. Wenn ich eine Version auswähle, wird mir ein Menü mit einer Liste von Aktionen wie Starten eines Containers, Ausführen in einen Container usw. präsentiert. Bevor ich eine Aktion starte, kopiert das Startskript Docker die Dateien aus dem Verzeichnis docker-version in das Hauptverzeichnis, so dass wir die Dateien immer an der gleichen Stelle haben, als ob wir eine einzelne Site betreiben würden.

Beachten Sie, dass diese Einrichtung nicht in Konflikt mit der Funktionsweise von Docker steht. Nachdem wir einen Docker -Container mit Docker-compose gestartet haben, können wir die Dateien docker-compose und die Umgebungsvariablen entfernen. Wenn Sie Docker zu einem bestimmten Zeitpunkt neu starten, werden einfach die Container neu gestartet, die vorher liefen, ohne dass diese Dateien benötigt werden.

Erweitern der Projektverzeichnisstruktur

Ich wollte den gesamten Code zwischen den Sites teilen, aber ich wollte, dass sie ihre eigenen Vorlagen, statischen Verzeichnisse, Protokolldateien usw. haben. Die neue Projektverzeichnisstruktur:

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

Der Code in der Anwendung wird gemeinsam genutzt. Docker-volumes ist ein Volume-Mount für Protokolldateien usw. Ein Unterschied zum Single-Site-Setup ist der Speicherort der Flask -Konfigurationsdatei config.py. Ich lade diese Datei in create_app() unter Verwendung der from_object()-Methode. Um sicherzustellen, dass die Datei gefunden werden kann, füge ich das Verzeichnis der Datei, das durch die Docker -Umgebungsvariablen angegeben wird, zu sys.path hinzu:

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])

Ein weiterer Unterschied zur Einzelplatzeinrichtung sind die Vorlagen. Ich möchte, dass es wie folgt funktioniert. Wenn das Site-Verzeichnis keine Vorlage enthält, fällt es auf das Verzeichnis der Anwendungsvorlagen zurück. Es ist sehr einfach, Jinja mitzuteilen, wo nach Vorlagen gesucht werden soll. Jinja unterstützt viele Loader, ich habe mich für den ChoiceLoader entschieden:

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
    ...

Schlussfolgerung

Hier stellte ich eine Möglichkeit vor, wie man den Code und (optional) Vorlagen zwischen mehreren Sites teilen kann, ohne eine Kopie des gesamten Verzeichnisbaums für eine neue Site zu erstellen. Obwohl es eine Menge Dinge gibt, die verbessert werden können, benutze ich diese Methode und bin froh, dass ich mir die Zeit genommen habe, sie zu implementieren.

Links / Impressum

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

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.