.. _deployment: .. index:: single: Deployment single: Git single: Sicherheit single: Docker single: Github single: Commit-Hooks Deployment ************ Hier ein paar Tipps, wie ein Projekt heutzutage deployed wird. Django selbst bietet eine Checkliste, was alles gemacht werden muss, um sauber uns sicher zu Deployen ``_ Git ==== Das Projekt sollte via ``git`` versioniert und bei ``github`` gehostet werden. GitHooks ========= kein Code sollte ins share repository wie ``github`` gehen, der schlecht formatiert ist oder Test-Fehler enthält. Um diesem Problem entgegenzuwirken, lassen sich sogenannte Hooks einrichten. Der Wichtigste Hook ist der ``pre-commit-hook``, der VOR dem Commit den Code testet und dann erst den Commit zulässt. Konfiguriert wird das ganze in einer ``pre-commit-config.yaml``-Datei. .. code-block:: bash repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.ref hooks: - id: check-docstring-first - id: check-merge-conflict - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-ast - id: check-toml - repo: https://gitlab.com/pycqa/flake8 rev: 3.9.2 hooks: - id: flake8 args: ['--config=setup.cfg', '--ignore=Fstable,E501,F405,F403'] exclude: ^events/tests/ - repo: local hooks: - id: django-test name: django-test entry: python manage.py test always_run: true pass_filenames: false language: system - repo: https://github.com/pycqa/isort rev: 5.9.3 hooks: - id: isort name: isort (python) Dieser Pre-Commit-Hook zum Beisiel prüft den Code auf flake8-Verstöße, führt mit ``manage.py test`` die Tests durch, sortiert die Imports mit ``isort`` und prüft merge-Konflikte, Yaml und Toml - Dateien. CI/CD - Pipeline ================= Heute kommt kein Projekt mehr ohne ``Continous Integration`` bzw. ``Continous Deployment`` aus. Eine Einführung findet sich hier: ``_ Docker ======= Wenn im Team gearbeitet wird, gibt es unweigerlich Unterschiede in der Konfiguration zwischen den lokalen Rechnern der einzelnen Entwickler. Ganz zu schweigen von dem Unterschied lokale Konfiguration mit der produktiven Konfiguration. Um diesem Problem entgegenzuwirken, wird heute fast ausschließlich mit Containern gearbeitet. So kann sichergestellt werden, dass jede lokale Instanz des Projekts inkl. der Peripherie wie Datenbank, Message-Broker, Celery etc, identisch mit der Produktiv-Instanz ist. Eine kleine Einführung gibt es hier: ``_ Ansonsten finden sich unzählige Tutorials im Internet. Docker Container sind einfach skalierbar und zum Beispiel mit ``Kubernetes`` orchestrierbar. eine einfache docker-compose - Datei für die lokale Entwicklungsumgebung könnte so aussehen: .. code-block:: yml version: '3.8' services: app: build: ./app command: > sh -c "python manage.py runserver 0.0.0.0:8000" volumes: - ./app/:/usr/src/app/ ports: - 8000:8000 env_file: - ./.env depends_on: - db - redis db: image: postgres:13.0-alpine volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_USER=basepro - POSTGRES_PASSWORD=basepro - POSTGRES_DB=basepro_dev redis: image: redis:alpine volumes: postgres_data: driver: local Auf Sicherheitslücken prüfen ======================================== Auf dem Livesystem sollte beim ersten Deploy festgestellt werden, ob es Sicherheitslücken gibt. Diese gleich fixen. .. code-block:: bash > python manage.py check --deploy WARNINGS: ?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems. Fehler still stellen ---------------------- Manche Fehler werden an anderere Stelle besser behoben. Zum Beispiel werden die HSTS-Header ( HTTP Strict-Transport-Security response header ) oft von NGINX gesetzt. Dann kann man die Fehlermeldungen in den ``settings.py`` auch muten: .. code-block:: python SILENCED_SYSTEM_CHECKS = ["security.W004"] Webserver ============== Bisher hatten wir zum Starten unserer Appliation den Runserver benutzt, den wir mit ``python manage.py runserver`` gestartet haben. Der Runserver ist für die Entwicklungsphase auf dem lokalen Rechner gedacht, nicht aber für den Produktivbetrieb. Die Gründe sind vielfältig: der Server ist nicht für hohen Traffic ausgelegt und es besteht auch nicht die Möglicheit, den Server zu tunen. Außerdem ist unsicher. In einem Live-System betreiben wir ``nginx`` als Proxyserver, der die Last verteilt und den Input weiterroutet an den Webserver ``gunicorn``. eigener Server =============== Das Endprodukt kann natürlich auf einem eigenen Server betrieben werden. Dazu nötig ist ein Linux-Betriebsystem, Firewall, eine Datenbank und so weiter. Idealerweise läuft auf diesem System Docker, dann lässt sich der Docker-Container nutzen. Als Server dient ``nginx``, der bei mehreren Docker-Containern auch gleich als Load-Balancer fungieren kann. Allerdings ist das mit Aufwand verbunden. Platform as a service ====================== Einfacher geht's mit ``Heroku``. Der hochspezialisierte Platform-as-a-service-Dienst übernimmt die schwierigen Aufgaben, die Infrastrutkur in Gang zu halten, während sich der Entwickler nur noch um die Software kümmern muss. Ein Tutorial dazu findet sich hier: ``_ Fehler loggen mit Rollbar oder Sentry ======================================= Moderne Plattformen mit vielen Tausenden Usern produzieren Fehler. Um diese Fehler komfortabel auszuwerten, nutzen wir kommerzielle Error-Tracking-Dienste, die diese Aufgabe für uns übernehmen. ``Rollbar`` zum Beispiel bietet Gratis-Accounts für kleine websites an. Projekt mit gunicorn starten ------------------------------ Um zu testen, ob das System soweit läuft, kann man es mit gunicorn starten. .. code-block:: bash gunicorn event_manager.wsgi