Docker für Trading-Bots: Deployment ohne Drama.
Ein Trading-Bot, der lokal läuft, ist ein Hobby. Ein Trading-Bot, der reproduzierbar auf jedem Server in fünf Minuten startet, sich nach einem Crash selbst neu hochfährt und keine Geheimnisse im Image trägt, ist Infrastruktur. Docker ist nicht der einzige Weg dorthin — aber für mich der pragmatischste.
Warum Docker für Trading-Bots.
Drei Gründe, in dieser Reihenfolge:
- Reproduzierbarkeit: Python-Version, Pandas-Version, TA-Lib-Build, Broker-SDK — exakt dieselbe Umgebung auf Laptop, Staging-VPS und Produktiv-Server. Keine „funktioniert bei mir"-Diskussionen mehr.
- Isolierung: Wenn ein Bot crasht oder Speicher leakt, ist nur sein Container betroffen. Datenbank, Monitoring und andere Strategien laufen weiter.
- Crash-Recovery: Mit
restart: unless-stoppedist ein gestürzter Bot in Sekunden wieder oben. Mit Health-Checks merken Sie sogar, wenn er „läuft", aber nicht mehr arbeitet.
Was Docker nicht löst: schlechte Strategien, Look-Ahead-Bias, Broker-Ausfälle. Docker macht Ihre Bots nicht profitabler — nur betreibbar.
Container-Architektur für ein typisches Setup.
Ein realistisches Bot-Deployment ist selten ein einzelner Container. Bei mir laufen typischerweise vier Services parallel:
- bot: die eigentliche Strategie-Engine (Python).
- postgres: persistente Trades, Positionen, Equity-Curve.
- prometheus: Metriken (PnL, Order-Latenz, Heartbeats).
- grafana: Dashboard, das ich morgens aufs Handy bekomme.
Alles über ein internes Docker-Netzwerk verbunden. Nach außen exponiert nur Grafana auf einem Reverse-Proxy mit Basic-Auth. Der Bot selbst hat keinen offenen Port — er ruft nur raus zum Broker.
Beispiel-Dockerfile für einen Python-Bot.
Ein knappes, produktionsnahes Image. Multi-Stage, damit Build-Abhängigkeiten nicht im Final-Image landen, und ein non-root User, weil Bots als root einfach unnötig sind:
# --- Build-Stage ---
FROM python:3.12-slim AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential gcc \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# --- Runtime-Stage ---
FROM python:3.12-slim
RUN useradd -m -u 1000 bot
WORKDIR /app
COPY --from=builder /root/.local /home/bot/.local
COPY --chown=bot:bot ./src ./src
USER bot
ENV PATH=/home/bot/.local/bin:$PATH \
PYTHONUNBUFFERED=1
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
CMD python -c "import socket; socket.create_connection(('localhost', 9100), 2)"
CMD ["python", "-m", "src.main"]
PYTHONUNBUFFERED=1 ist nicht optional — ohne das landen Ihre Logs in
irgendeinem Buffer und Sie sehen Crashes erst beim Container-Restart.
docker-compose.yml für das ganze Setup.
services:
bot:
build: ./bot
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DB_URL: postgresql://bot:${DB_PASS}@postgres:5432/trading
BROKER_API_KEY_FILE: /run/secrets/broker_key
secrets:
- broker_key
networks: [internal]
logging:
driver: json-file
options: { max-size: "10m", max-file: "5" }
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: trading
POSTGRES_USER: bot
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bot"]
interval: 10s
retries: 5
networks: [internal]
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- promdata:/prometheus
networks: [internal]
grafana:
image: grafana/grafana:latest
restart: unless-stopped
ports: ["127.0.0.1:3000:3000"]
volumes:
- grafanadata:/var/lib/grafana
networks: [internal]
volumes:
pgdata:
promdata:
grafanadata:
networks:
internal:
secrets:
broker_key:
file: ./secrets/broker_key.txt
Health-Checks, Auto-Restart, Logging.
Drei Themen, die Anfänger gerne übergehen und an denen später die Nächte hängen:
- Health-Check ist nicht „Prozess läuft", sondern „Prozess arbeitet". Ein guter Bot-Healthcheck prüft: letzter Heartbeat < 60 Sek., DB-Verbindung steht, Broker-Session ist authentifiziert. Bei Fehlschlag markiert Docker den Container als unhealthy — und Orchestratoren wie Swarm oder Kubernetes restarten ihn automatisch.
- Restart-Policy:
unless-stoppedist fast immer richtig.alwaysstartet auch, nachdem Sie den Container bewusst gestoppt haben — das wollen Sie selten. - Logging: Default-Logging schreibt unbegrenzt in
/var/lib/docker/containers/…. Nach drei Monaten ist die Disk voll. Immermax-sizeundmax-filesetzen oder direkt auf einen Log-Aggregator (Loki, Vector) schicken.
Secrets — nicht ins Image, niemals.
Drei Wege, API-Keys in Container zu bekommen, in aufsteigender Qualität:
- Environment-Variablen (z. B. via
.env): okay für persönliche Setups, sichtbar viadocker inspectund in Logs von Crash-Reports. - Docker Secrets (Mount unter
/run/secrets/…): Datei-basiert, nicht in der Env, nicht indocker inspect. Das Minimum für produktives Setup. - Vault / KMS: Bot holt sich Keys zur Laufzeit aus HashiCorp Vault oder AWS Secrets Manager, kurzlebige Tokens. Für institutionelle Setups Standard.
Was Sie nie tun: API-Keys in ENV-Anweisungen im Dockerfile,
in git-getrackten Configs, oder als Argument an docker run.
Alle drei landen in Logs, Image-Layern oder Bash-History.
Update-Strategien.
Strategie ändern, Code pushen, Image bauen, neu deployen — wie ohne Trade-Verluste? Drei Optionen:
- Recreate: alten Container stoppen, neuen starten. Downtime: 2–5 Sek. Für die meisten Strategien akzeptabel, vor allem wenn man außerhalb der Handelszeiten deployed.
- Rolling Update: bei mehreren Bot-Instanzen einer nach dem anderen ersetzen. Sinnvoll, wenn ein Bot Multi-Account-Strategien fährt und nicht alle Konten gleichzeitig blind sein dürfen.
- Blue-Green: neues Image neben dem alten hochfahren, validieren, Traffic umschalten. Im Trading bedeutet „Traffic umschalten" meist: alter Bot schließt Positionen sauber, neuer Bot übernimmt mit Flat-Start. Ich nutze das nur für größere Releases mit Schema-Änderungen.
Mein Default: docker compose pull && docker compose up -d in der
Mittagspause, wenn meine Strategien gerade keine offenen Positionen halten. Pragmatisch,
funktioniert.
Wann Docker nicht lohnt.
Drei Fälle, in denen ich Kunden eher abrate:
- Ein einzelner Bot auf einem dedizierten VPS: wenn Sie wirklich nur eine Strategie laufen lassen, ist ein
systemd-Service mit einer venv genauso stabil und deutlich weniger Lern-Overhead. - MetaTrader 5 / cTrader auf Wine: technisch möglich, in der Praxis fragil. Ich empfehle hier dedizierte Windows-VPS pro Account, kein Docker.
- Strategien mit GPU-Inferenz auf Apple Silicon: Docker Desktop hat hier immer noch Schwächen. Für lokale Entwicklung okay, für 24/7-Betrieb nicht.
Übergang zu Kubernetes.
Ab wann Kubernetes? Meine Faustregel: wenn Sie mehr als ~20 Bot-Container betreiben, mehrere physische Server orchestrieren, oder Multi-Region-Failover brauchen. Darunter ist Docker Compose oder Docker Swarm der bessere Hebel pro Stunde Lernzeit.
Kubernetes bringt Ressourcen-Limits, automatisches Rescheduling bei Node-Ausfall, Pod-Anti-Affinity (zwei Bots derselben Strategie laufen nie auf demselben Host) und Helm-Charts als versionierbare Deployment-Beschreibung. Wer einmal einen Bot-Park mit 50+ Strategien betreibt, will das nicht mehr missen. Wer drei Strategien auf einem Hetzner-VPS hat, braucht es nicht.
Sie wollen Ihre Trading-Bots aus dem „läuft auf meinem Laptop"-Zustand in ein sauberes Container-Deployment überführen? Erstgespräch buchen — wir bauen die Infrastruktur, die zu Ihrem Strategie-Stack passt.