Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Cloud / Hosting 05.07.2026 · 9 min Lesezeit

Gotenberg mit Docker installieren: Entwicklerfreundliche Docker-API für PDF-Konvertierung

Gotenberg ist eine zustandslose REST-API im Docker-Container, die HTML, URLs und Office-Dokumente per multipart-POST in PDFs umwandelt. Die Anleitung zeigt compose.yaml, .env, Basic Auth und die ersten curl-Tests.

Geprüft am 30.09.2026 · für gotenberg 8.37.0

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Symbolbild zur Anleitung: Gotenberg mit Docker installieren

Wer in einer Anwendung PDF-Dateien erzeugen muss, kennt das Problem: LibreOffice auf dem Server installieren, Headless-Chromium konfigurieren, Abhängigkeiten verwalten – und das auf jedem Deployment-Ziel erneut. Gotenberg nimmt Ihnen diese Arbeit ab. Die in Go geschriebene REST-API verpackt Headless Chromium und LibreOffice in einen einzigen Docker-Container. Entwickler schicken Dateien per multipart/form-data an den Container und erhalten ein fertiges PDF zurück. Der Betrieb erfordert weder Datenbank noch zusätzliche Dienste.

Voraussetzungen

  1. Docker Engine 24.x oder neuer mit Docker Compose Plugin v2 (docker compose ohne Bindestrich). Wie Sie das auf einem Linux-Host einrichten, erklärt die Anleitung Docker und Docker Compose auf Linux installieren.
  2. Beliebiger Linux-Host, VM oder NAS mit Docker-Unterstützung (amd64, arm64, armv7, 386 und ppc64le; damit auch Raspberry Pi und Apple Silicon).
  3. Mindestens 512 MB freier RAM; bei regelmäßigen LibreOffice-Konvertierungen unter Last lieber 1–2 GB reservieren.
  4. curl zum Testen der API.
  5. Optional: Reverse Proxy (Caddy, Nginx, Traefik) für TLS-Terminierung, wenn der Dienst von außen erreichbar sein soll. Die Anleitung Caddy als Reverse Proxy einrichten zeigt den Weg.
  6. Eine Testdatei (.docx oder .html) für die Verifikation nach dem Start.

Schritt 1: Projektordner anlegen

Legen Sie einen eigenen Ordner für den Gotenberg-Stack an. Er enthält nur die Konfigurationsdateien, da Gotenberg zustandslos ist und keine Datenbank oder persistenten Volumes benötigt.

mkdir -p /opt/gotenberg
cd /opt/gotenberg

Wer den Stack im Home-Verzeichnis bevorzugt, nimmt entsprechend ~/gotenberg.

Verifizieren: ls /opt/gotenberg – der Ordner ist vorhanden. Der Befehl gibt keine Fehlermeldung zurück.

Schritt 2: .env-Datei anlegen

Die .env-Datei enthält alle anpassbaren Werte. Zugangsdaten für Basic Auth stehen hier und nicht in der compose.yaml.

# /opt/gotenberg/.env

# API-Konfiguration
API_TIMEOUT=60s
API_BODY_LIMIT=20MB

# Basic Auth (in Produktion auf true setzen)
API_ENABLE_BASIC_AUTH=false
GOTENBERG_API_BASIC_AUTH_USERNAME=admin
GOTENBERG_API_BASIC_AUTH_PASSWORD=sicheres_passwort_hier_aendern

# Logging
LOG_LEVEL=info
LOG_STD_FORMAT=auto

# Chromium-Modul
CHROMIUM_MAX_CONCURRENCY=6
CHROMIUM_RESTART_AFTER=100
CHROMIUM_AUTO_START=false

# LibreOffice-Modul
LIBREOFFICE_RESTART_AFTER=10
LIBREOFFICE_AUTO_START=false

Für Produktion setzen Sie API_ENABLE_BASIC_AUTH=true und ein starkes Passwort (Schritt 8). Für sehr große DOCX- oder XLSX-Dateien erhöhen Sie API_TIMEOUT auf 120s oder mehr; der Standard liegt bei 30 Sekunden, hier bereits auf 60s erweitert. Alle Variablennamen entsprechen den Gotenberg-Flags in Großbuchstaben (--api-timeout wird API_TIMEOUT).

Verifizieren: cat /opt/gotenberg/.env – alle Variablen sind korrekt eingetragen, keine Syntaxfehler.

Schritt 3: compose.yaml erstellen

Die folgende compose.yaml startet Gotenberg mit Ressourcenbegrenzung, Health-Check und sicherem Port-Binding. Das Image-Tag ist auf 8.37.0 festgelegt (Stand: September 2026), damit Updates nur bewusst erfolgen. Das Tag :8 folgt automatisch dem neuesten 8.x-Release.

# /opt/gotenberg/compose.yaml
services:
  gotenberg:
    image: gotenberg/gotenberg:8.37.0
    container_name: gotenberg
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      API_TIMEOUT: ${API_TIMEOUT:-60s}
      API_BODY_LIMIT: ${API_BODY_LIMIT:-20MB}
      API_ENABLE_BASIC_AUTH: ${API_ENABLE_BASIC_AUTH:-false}
      GOTENBERG_API_BASIC_AUTH_USERNAME: ${GOTENBERG_API_BASIC_AUTH_USERNAME:-}
      GOTENBERG_API_BASIC_AUTH_PASSWORD: ${GOTENBERG_API_BASIC_AUTH_PASSWORD:-}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      LOG_STD_FORMAT: ${LOG_STD_FORMAT:-auto}
      CHROMIUM_MAX_CONCURRENCY: ${CHROMIUM_MAX_CONCURRENCY:-6}
      CHROMIUM_RESTART_AFTER: ${CHROMIUM_RESTART_AFTER:-100}
      CHROMIUM_AUTO_START: ${CHROMIUM_AUTO_START:-false}
      LIBREOFFICE_RESTART_AFTER: ${LIBREOFFICE_RESTART_AFTER:-10}
      LIBREOFFICE_AUTO_START: ${LIBREOFFICE_AUTO_START:-false}
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: "1.0"
        reservations:
          memory: 512M
          cpus: "0.2"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

Der Port ist bewusst auf 127.0.0.1:3000:3000 beschränkt. Gotenberg hat im Standardmodus keine Authentifizierung; ein freigegebener Port erlaubt jedem im Netz beliebige Konvertierungen. Der Healthcheck nutzt curl, das im offiziellen Image enthalten ist. Sollen andere Docker-Services im gleichen Stack auf Gotenberg zugreifen, brauchen sie gar keinen exportierten Port: Sie erreichen den Container intern über http://gotenberg:3000.

Docker-Netzwerke und die interne Service-Kommunikation erklärt die Anleitung Docker-Netzwerke und Volumes richtig nutzen.

Verifizieren: docker compose config im Projektordner zeigt die aufgelöste Konfiguration inklusive der .env-Werte – keine Fehlermeldung, alle Variablen befüllt.

Schritt 4: Container starten

Vom Projektordner aus den Stack starten:

cd /opt/gotenberg
docker compose up -d

Docker lädt das Image herunter (rund 700 MB komprimiert für das Vollimage mit Chromium und LibreOffice) und startet den Container im Hintergrund. Der erste Start kann je nach Internetverbindung einige Minuten dauern.

Status und Logs prüfen:

# Container-Status anzeigen
docker compose ps

# Logs verfolgen (Ctrl+C zum Beenden)
docker compose logs -f gotenberg

Erwartete Ausgabe von docker compose ps:

NAME        IMAGE                    STATUS
gotenberg   gotenberg/gotenberg:8.37.0    Up 30 seconds (healthy)

In den Logs meldet Gotenberg nach wenigen Sekunden, dass der Server auf Port 3000 lauscht.

Verifizieren: docker compose ps zeigt STATUS = Up ... (healthy). Zeigt der Status (health: starting), warten Sie kurz und prüfen Sie erneut; der Health-Check hat 10 Sekunden Anlaufzeit.

Schritt 5: API testen – Health-Check und erste Konvertierung

Zuerst den Health-Endpunkt aufrufen:

curl -I http://localhost:3000/health

Erwartete Antwort:

HTTP/1.1 200 OK
Content-Type: application/json

Alternativ zeigt curl http://localhost:3000/health ein JSON-Objekt mit dem Status beider Module (Chromium, LibreOffice).

Eine Webseite per URL in PDF konvertieren

curl --request POST \
  http://localhost:3000/forms/chromium/convert/url \
  --form url=https://example.com \
  -o /tmp/example-com.pdf

Eine DOCX-Datei in PDF konvertieren

curl --request POST \
  http://localhost:3000/forms/libreoffice/convert \
  --form files=@/pfad/zu/dokument.docx \
  -o /tmp/ausgabe.pdf

Eine lokale HTML-Datei in PDF konvertieren

curl --request POST \
  http://localhost:3000/forms/chromium/convert/html \
  --form files=@/pfad/zu/seite.html \
  -o /tmp/seite.pdf

Wenn Basic Auth aktiv ist (API_ENABLE_BASIC_AUTH=true), muss bei jedem curl-Aufruf --user admin:passwort ergänzt werden.

Verifizieren: Die erzeugten PDF-Dateien unter /tmp/ sind vorhanden (ls -lh /tmp/*.pdf) und lassen sich öffnen. Eine leere oder 0-Byte-Datei deutet auf einen Konvertierungsfehler hin – dann docker compose logs gotenberg auf Fehlermeldungen prüfen.

Eckdaten im Überblick

ParameterWertHinweis
Imagegotenberg/gotenberg:8.37.0Vollimage (Chromium + LibreOffice); aktuell 8.37.0
Image-Varianten:8-chromium, :8-libreoffice~30–40 % kleiner, jeweils nur ein Modul
Port3000/tcpNur auf localhost binden: 127.0.0.1:3000:3000
VolumeskeineZustandslos, keine persistenten Daten nötig
DatenbankkeineEinziger Container genügt
Architekturamd64, arm64, armv7, 386, ppc64leRaspberry Pi und Apple Silicon unterstützt
RAM (min.)512 MBUnter LibreOffice-Last eher 1–2 GB
Chromium-Parallelitätbis 6 (einstellbar)CHROMIUM_MAX_CONCURRENCY
LibreOffice-Parallelität1 (sequenziell)Bei hoher Last: mehrere Container-Instanzen
API-EndpunktModulUnterstützte Formate (Auswahl)
POST /forms/chromium/convert/urlChromiumBeliebige URL → PDF
POST /forms/chromium/convert/htmlChromiumHTML-Datei(en) → PDF
POST /forms/chromium/convert/markdownChromiumMarkdown + HTML-Template → PDF
POST /forms/libreoffice/convertLibreOfficeDOCX, XLSX, PPTX, ODT, ODS, RTF, CSV und 100+ weitere
GET /health–Status beider Module, 200 OK wenn bereit

Schritt 7: Updates einspielen

Da Gotenberg zustandslos ist, genügt für ein Update ein neues Tag. Tragen Sie in der compose.yaml die neue Version ein (Release Notes auf GitHub prüfen) und führen Sie aus:

cd /opt/gotenberg
docker compose pull
docker compose up -d

Docker zieht das neue Image, stoppt den laufenden Container und startet ihn mit dem aktualisierten Image neu. Die Unterbrechung dauert wenige Sekunden. Automatische Container-Updates beschreibt die Anleitung Watchtower mit Docker: Container automatisch aktualisieren.

Verifizieren: Nach dem Update zeigen docker compose ps wieder healthy und curl -I http://localhost:3000/health 200 OK.

Schritt 8: Optional – Basic Auth und Reverse Proxy aktivieren

Soll Gotenberg über das Internet erreichbar sein, sind zwei Maßnahmen Pflicht:

Basic Auth aktivieren: Setzen Sie in der .env API_ENABLE_BASIC_AUTH=true und ein starkes Passwort, dann docker compose up -d. Alle curl-Anfragen brauchen danach --user admin:passwort. Seit 8.x unterstützt Gotenberg alternativ OIDC-Bearer-Tokens (API_ENABLE_OIDC_AUTH).

Reverse Proxy mit TLS vorschalten: Gotenberg selbst terminiert kein TLS. Schalten Sie für HTTPS einen Reverse Proxy (Caddy, Nginx Proxy Manager oder Traefik) vor. Der Proxy leitet Anfragen an http://gotenberg:3000 weiter – bei gemeinsamen Docker-Netzwerken ohne exportierten Port.

Weitere Maßnahmen zu Secrets und Healthchecks beschreibt die Anleitung Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.

Verifizieren: Senden Sie mit aktivierter Basic Auth eine Konvertierung ohne Zugangsdaten; der Server antwortet mit 401 Unauthorized. Mit --user admin:passwort kommt 200 OK und das PDF zurück.

Troubleshooting / Typische Fehler

  1. 503 Supervisor run task: context deadline exceeded: Das Timeout wurde überschritten. Ursache: großes DOCX/XLSX oder langsamer Host. Lösung: API_TIMEOUT=120s in der .env setzen und docker compose up -d ausführen.
  2. Layout-Verschiebungen bei DOCX-zu-PDF: Microsoft-Schriften fehlen aus Lizenzgründen; das Image bringt metrisch kompatible Ersatzschriften mit (Liberation, Carlito, Caladea). Weichen Firmenschriften ab, erstellen Sie ein eigenes Dockerfile auf Basis FROM gotenberg/gotenberg:8.37.0 und fügen die Schriften per COPY nach /usr/local/share/fonts hinzu.
  3. Port versehentlich öffentlich freigegeben: Wenn 0.0.0.0:3000:3000 statt 127.0.0.1:3000:3000 gesetzt ist, ist Gotenberg ohne Auth von außen erreichbar. Korrigieren Sie das sofort und führen Sie docker compose up -d aus. Dasselbe gilt für die Kurzform 3000:3000.
  4. HTML referenziert http://localhost:8080 – kein Zugriff möglich: Im Container zeigt localhost auf Gotenberg selbst, nicht auf den Docker-Host. Lösung: Docker-interne DNS-Namen verwenden (http://mein-app-service:8080) oder unter Docker Desktop host.docker.internal nutzen.
  5. Bilder und CSS fehlen im generierten PDF: Externe Ressourcen müssen per erreichbarer URL eingebunden oder als zusätzliche Dateien im multipart-Request mitgeschickt werden (--form files=@style.css --form files=@logo.png).
  6. Chromium Print Error -32000 / Speichermangel: Sehr große HTML-Seiten überfordern Chromium. Lösung: deploy.resources.limits.memory auf 2G erhöhen.
  7. LibreOffice-Timeouts unter Last: LibreOffice läuft als einzelne Instanz mit Lock – Anfragen stellen sich sequenziell in die Warteschlange. Lösung: mehrere Gotenberg-Container hinter einem Load Balancer betreiben.
  8. Fehler nicht lesbar: LOG_LEVEL=debug setzen. Bei HTTP-400-Fehlern immer den Response-Body lesen – Gotenberg gibt dort das fehlerhafte Formularfeld im Klartext an.

Häufige Fragen

Braucht Gotenberg eine Datenbank oder Redis?

Nein. Gotenberg ist vollständig zustandslos – kein Redis, keine SQL-Datenbank, keine externe Abhängigkeit. Temporäre Dateien werden intern verwaltet und beim Container-Neustart gelöscht. Ein einzelner Container genügt.

Welches Image-Tag sollte ich verwenden?

Für Reproduzierbarkeit legen Sie die Version fest, etwa gotenberg/gotenberg:8.37.0. Das Tag :8 folgt automatisch dem neuesten 8.x-Release, :latest kann auf eine neue Hauptversion springen und ist für Produktion nicht zu empfehlen.

Kann ich nur HTML oder nur Office-Dokumente konvertieren – ohne das große Vollimage?

Ja. Gotenberg bietet zwei schlankere Varianten: gotenberg/gotenberg:8-chromium (nur Chromium, ca. 30 % kleiner – für HTML, URL, Markdown) und gotenberg/gotenberg:8-libreoffice (nur LibreOffice, ca. 40 % kleiner – für Office-Formate). Für gemischte Workloads nehmen Sie das Vollimage.

Kann Gotenberg mehrere Dokumente gleichzeitig konvertieren?

Das hängt vom Modul ab. Chromium unterstützt bis zu 6 parallele Konvertierungen (einstellbar über CHROMIUM_MAX_CONCURRENCY). LibreOffice läuft als einzelne Instanz mit Lock – Anfragen werden sequenziell verarbeitet. Bei hoher LibreOffice-Last hilft nur horizontales Skalieren: mehrere Gotenberg-Container hinter einem Load Balancer.

Wie aktiviere ich Authentifizierung?

In der .env API_ENABLE_BASIC_AUTH=true setzen sowie GOTENBERG_API_BASIC_AUTH_USERNAME und GOTENBERG_API_BASIC_AUTH_PASSWORD mit echten Werten belegen, dann docker compose up -d. Bei curl-Anfragen --user benutzername:passwort ergänzen. Für den Produktionseinsatz ist zusätzlich ein Reverse Proxy mit TLS empfohlen.

Läuft Gotenberg auf ARM-Hardware (Raspberry Pi, Apple Silicon)?

Ja. Das offizielle Image unterstützt amd64, arm64, armv7, 386 und ppc64le. Docker wählt beim Pull automatisch die passende Variante.

Kann ich Webhooks nutzen, um auf Konvertierungsergebnisse zu warten?

Ja. Geben Sie den Header Gotenberg-Webhook-Url mit der Rückruf-URL mit, dazu zwingend Gotenberg-Webhook-Events-Url (früher Gotenberg-Webhook-Error-Url) für Fehler- und Statusmeldungen. Gotenberg antwortet sofort und sendet das fertige PDF per POST an die Rückruf-URL, nützlich bei großen Dokumenten.

Fazit

Gotenberg bindet PDF-Konvertierung mit einem einzelnen Container ohne Datenbank und Host-Abhängigkeiten in bestehende Abläufe ein: multipart-POST hinein, PDF heraus. Für HTML-zu-PDF und Office-Konvertierung ist das wartungsärmer als selbst installierte LibreOffice- oder wkhtmltopdf-Setups. Beachten Sie, dass LibreOffice Anfragen nacheinander verarbeitet; planen Sie bei hoher Last mehrere Instanzen ein.

Weiterführende Anleitungen und Quellen

  1. Paperless-ngx mit Docker einrichten: papierlose Dokumentenverwaltung mit OCR – ergänzt Gotenberg ideal für automatisierte Dokumenten-Workflows.
  2. Stirling-PDF mit Docker: der lokale PDF-Werkzeugkasten – für manuelle PDF-Operationen im Browser statt per API.
  3. Docker und Docker Compose auf Linux installieren: die Self-Hosting-Grundlage
  4. Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS

Offizielle Quellen: Gotenberg Dokumentation und Gotenberg auf GitHub.

Passende Anleitungen auf S-EDV

  1. netcup Local Block Storage bestellen, einrichten und unter Linux einbinden