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.
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/
Mehr erfahren
Docker Docker-compose Flask
Neueste
- Ausblenden der Primärschlüssel der Datenbank UUID Ihrer Webanwendung
- Don't Repeat Yourself (DRY) mit Jinja2
- SQLAlchemy, PostgreSQL, maximale Anzahl von Zeilen pro user
- Anzeige der Werte in den dynamischen Filtern SQLAlchemy
- Sichere Datenübertragung mit Public Key Verschlüsselung und pyNaCl
- rqlite: eine hochverfügbare und distverteilte SQLite -Alternative
Meistgesehen
- Verwendung von Pythons pyOpenSSL zur Überprüfung von SSL-Zertifikaten, die von einem Host heruntergeladen wurden
- Verwendung von UUIDs anstelle von Integer Autoincrement Primary Keys mit SQLAlchemy und MariaDb
- PyInstaller und Cython verwenden, um eine ausführbare Python-Datei zu erstellen
- Verbindung zu einem Dienst auf einem Docker -Host von einem Docker -Container aus
- SQLAlchemy: Verwendung von Cascade Deletes zum Löschen verwandter Objekte
- Flask RESTful API Validierung von Anfrageparametern mit Marshmallow-Schemas