← Alle Insights

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:

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:

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:

Secrets — nicht ins Image, niemals.

Drei Wege, API-Keys in Container zu bekommen, in aufsteigender Qualität:

  1. Environment-Variablen (z. B. via .env): okay für persönliche Setups, sichtbar via docker inspect und in Logs von Crash-Reports.
  2. Docker Secrets (Mount unter /run/secrets/…): Datei-basiert, nicht in der Env, nicht in docker inspect. Das Minimum für produktives Setup.
  3. 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:

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:

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