Viele Hobby- und Nebenprojekte scheitern nicht am Code, sondern am Deployment. Manuell per FTP hochladen, auf dem Server „mal schnell etwas fixen“, unterschiedliche Python-Versionen – all das führt früher oder später zu Chaos.
In diesem Beitrag zeige ich mein state-of-the-art Deployment-Setup, mit dem ich:
- lokal schnell entwickle
- automatisch deploye
- reproduzierbar und sicher betreibe
- ohne Kubernetes-Overkill auskomme
🧠 Die Grundidee
Der Server ist ausführend, nicht kreativ.
GitHub ist die Wahrheit.
Automatisierung erledigt den Rest.
Der Code entsteht lokal, nicht auf dem Server. Der Server bekommt Code nur automatisiert.
🔁 Der komplette Weg des Codes
[ PyCharm ]
|
| git push
v
[ GitHub Repository ]
|
| GitHub Actions (Push-Trigger)
v
[ SSH → Server ]
|
| git reset + docker build
v
[ Neuer Container ]
|
v
[ Traefik → Browser ]
1️⃣ Lokale Entwicklung ohne Docker
Ich entwickle lokal direkt mit Python:
- PyCharm
- virtuelles Environment (venv)
uvicorn --reloadfür sofortiges Feedback
Vorteile:
- extrem schnell
- direktes Debugging
- kein Warten auf Docker-Builds
Docker ist kein Entwicklungstool, sondern ein Lieferformat.
2️⃣ GitHub als Single Source of Truth
Nach dem Entwickeln reicht:
git commit
git push
Wichtig:
- Der Server pusht niemals Code
- GitHub ist die einzige Wahrheit
- Jede Änderung ist versioniert und nachvollziehbar
Das verhindert:
- „Works on my machine“-Probleme
- Drift zwischen Server und Repository
- manuelle Hotfixes auf dem Server
3️⃣ Automatisches Deployment mit GitHub Actions
GitHub Actions ist so konfiguriert, dass jeder Push auf den main-Branch automatisch ein Deployment startet.
Es gibt:
- keinen manuellen SSH-Login
- keinen Deployment-Knopf
- keine Sonderwege
GitHub startet dafür eine temporäre Runner-VM, die den Deploy übernimmt.
4️⃣ Sicheres Deploy per SSH
Der GitHub-Runner verbindet sich per SSH mit dem Server:
- dedizierter Benutzer (
deploy) - Authentifizierung ausschließlich per SSH-Key
- keine Passwörter
Wichtig:
Der Server ruft GitHub nicht an – GitHub deployt aktiv auf den Server.
5️⃣ Reproduzierbares Update auf dem Server
Auf dem Server werden folgende Befehle ausgeführt:
git fetch --all
git reset --hard origin/main
docker compose up -d --build
Das garantiert:
- Der Server entspricht exakt dem GitHub-Stand
- Keine Merges, kein Drift
- Ein neuer Docker-Container wird gebaut
- Der alte Container wird sauber ersetzt
Immutable Deploys statt Bastellösungen.
6️⃣ Warum Docker nur auf dem Server läuft
Im Docker-Container laufen:
- ein kleines Linux-Userspace
- Python 3.12
- alle Abhängigkeiten
- der Applikationscode
Aber:
- kein eigener Kernel
- kein virtuelles Betriebssystem wie bei VMs
Container teilen sich den Kernel des Hosts – deshalb sind sie leicht und schnell.
Lokal verzichte ich bewusst auf Docker:
- schnelleres Arbeiten
- besseres Debugging
- weniger Overhead
7️⃣ Traefik als Reverse Proxy (File Provider)
Traefik übernimmt:
- HTTPS (Let’s Encrypt)
- Host-Routing
- Weiterleitung an Docker-Container
Wichtiges Detail:
- kein Docker-Socket
- Routing ausschließlich über File Provider
Das sorgt für klare Trennung zwischen Routing, Applikation und Deployment.
🧠 Warum dieses Setup state of the art ist
- klare Trennung von Entwicklung und Betrieb
- vollständig automatisiert
- reproduzierbar
- sicher
- leicht verständlich
- kein Kubernetes-Overkill
Der Server ist austauschbar.
GitHub ist die Wahrheit.
Automatisierung ist der Standard.
🔁 Kurz gesagt
Ich entwickle lokal, pushe nach GitHub und lasse GitHub Actions automatisch einen neuen Docker-Container auf dem Server bauen und starten – ohne manuelles Eingreifen.
🔚 Fazit
Für kleine bis mittlere Web-Services auf einem VPS ist dieses Setup modern, professionell und praxiserprobt. Es skaliert sauber, ohne unnötige Komplexität einzuführen.