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