Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Server & Netzwerk 14.08.2026 · 10 min Lesezeit

Discourse mit Docker installieren: Modernes Community-Forum für KMU und Open-Source-Projekte

Discourse ist mit 47.000+ GitHub-Stars das meistgenutzte Open-Source-Forum weltweit. Diese Anleitung zeigt, wie du Discourse mit Docker Compose (Bitnami-Distribution) plattformneutral aufrichtest – inklusive PostgreSQL, Redis, Sidekiq, SMTP und vollständiger Verifikation nach jedem Schritt.

Discourse mit Docker installieren: Modernes Community Forum für KMU und Open Source Projekte mit Benutzergruppen, Rollen und Rechten, Plugins, Mehrsprachigkeit, Sicherheit, Backups und skalierbarer Docker Server Infrastruktur. KI-generiert

Discourse ist das meistgenutzte Open-Source-Forum-System der Welt – mit über 47.000 GitHub-Stars und aktivem Maintainer-Team. Ob Support-Portal für ein SaaS-Produkt, interne Wissensdatenbank, Entwickler-Community oder Kunden-Ökosystem: Discourse liefert von Haus aus Kategorien, Tags, Benachrichtigungen, vollständige E-Mail-Integration, Single Sign-On (Discourse Connect), Reaktionen und ein umfangreiches Plugin-System. Wer bisher auf proprietäre Foren-SaaS-Produkte gesetzt hat, bekommt hier eine vollwertige Alternative, die auf dem eigenen Server läuft. Diese Anleitung führt dich Schritt für Schritt durch eine plattformneutrale Installation per Docker Compose – mit der Bitnami-Distribution, die als einzige einen sauberen docker compose up-Workflow ohne proprietären Launcher bietet.

Voraussetzungen

  1. Docker Engine 20.10+ und Docker Compose v2 (Befehl: docker compose, nicht docker-compose) auf dem Host installiert – falls noch nicht vorhanden, nutze die Docker-und-Compose-Grundlagenanleitung.
  2. Linux-Host, VM oder NAS mit mindestens 2 GB RAM, 2 CPU-Kernen und 20 GB freiem Speicherplatz (Discourse-Empfehlung: 2 GB RAM für Produktion).
  3. Öffentlich erreichbarer Domainname (z. B. forum.beispiel.de) mit DNS-A-Eintrag auf die Server-IP – ohne korrekten Hostnamen erzeugt Discourse fehlerhafte interne Links.
  4. SMTP-Zugangsdaten eines externen Maildienstes (Mailgun, SendGrid, Postmark oder eigener Mailserver) – ohne funktionierende E-Mail ist Discourse nicht vollständig nutzbar.
  5. Optional, aber für Produktion empfohlen: ein Reverse Proxy mit HTTPS (Caddy, Traefik oder Nginx Proxy Manager). Ohne TLS fehlen Secure-Cookies und einige Discourse-Features funktionieren nicht korrekt.

Schritt 1: Projektordner und Verzeichnisstruktur anlegen

Lege einen dedizierten Ordner an, in dem alle Konfigurationsdateien für Discourse zusammenliegen. So bleibt das Setup übersichtlich und lässt sich leicht sichern.

sudo mkdir -p /opt/discourse
cd /opt/discourse

Im nächsten Schritt erstellst du dort zwei Dateien: .env für alle Secrets und compose.yaml für die Container-Definitionen. Trenne Secrets konsequent von der Compose-Konfiguration – so kannst du die compose.yaml versionieren, ohne Passwörter preiszugeben.

Verifizieren: Der Ordner existiert und du befindest dich darin.

ls -la /opt/discourse
# Erwartete Ausgabe: leeres Verzeichnis (nur . und ..)

Schritt 2: .env-Datei mit Secrets anlegen

Alle sensiblen Werte kommen in eine .env-Datei, die Docker Compose automatisch einliest. Passe jeden Wert an deine Umgebung an – insbesondere DISCOURSE_HOST, der ohne https:// und ohne abschließenden Slash angegeben werden muss.

# /opt/discourse/.env
# --- Discourse Hostkonfiguration ---
DISCOURSE_HOST=forum.beispiel.de
DISCOURSE_SITE_NAME=Mein Forum

# --- Admin-Account (wird beim ersten Start erstellt) ---
DISCOURSE_ADMIN_USER=admin
DISCOURSE_ADMIN_PASSWORD=sehrSicheresPasswort2026!
DISCOURSE_ADMIN_EMAIL=admin@beispiel.de

# --- Datenbankpasswörter ---
DB_PASSWORD=einSicheresDbPasswort42
REDIS_PASSWORD=einSicheresRedisPasswort42

# --- SMTP-Konfiguration (zwingend erforderlich) ---
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@mg.beispiel.de
SMTP_PASSWORD=deinSmtpPasswort
SMTP_PROTOCOL=tls

Schütze die Datei sofort mit restriktiven Rechten – sie enthält alle Passwörter:

chmod 600 /opt/discourse/.env

Wichtig: DISCOURSE_HOST muss exakt der öffentliche Hostname sein, auf dem das Forum erreichbar ist. Falsche Werte wie https://forum.beispiel.de/ führen zu kaputten internen Links und CSP-Fehlern. Setze außerdem niemals ALLOW_EMPTY_PASSWORD=yes in einer Produktionsumgebung – das öffnet die Datenbank ohne Passwortschutz.

Verifizieren:

stat /opt/discourse/.env
# Erwartete Ausgabe: Access: (0600/-rw-------) -- nur root darf lesen

Schritt 3: compose.yaml erstellen

Die folgende compose.yaml startet vier Dienste: PostgreSQL mit Healthcheck, Redis mit Healthcheck, den Discourse-Webserver und den Sidekiq-Worker für Hintergrundjobs (E-Mail-Versand, Benachrichtigungen, Wartung). Discourse und Sidekiq verwenden dabei dasselbe Image – nur der Startbefehl unterscheidet sie. Das gemeinsam gemountete discourse_data-Volume ist architektonisch zwingend: Sidekiq benötigt die Rails-Umgebung aus diesem Volume.

services:
  postgresql:
    image: docker.io/bitnami/postgresql:latest
    restart: unless-stopped
    volumes:
      - postgresql_data:/bitnami/postgresql
    environment:
      - POSTGRESQL_USERNAME=bn_discourse
      - POSTGRESQL_DATABASE=bitnami_discourse
      - POSTGRESQL_PASSWORD=${DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U bn_discourse -d bitnami_discourse"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: docker.io/bitnami/redis:latest
    restart: unless-stopped
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD}
    volumes:
      - redis_data:/bitnami/redis
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  discourse:
    image: docker.io/bitnami/discourse:2026
    restart: unless-stopped
    ports:
      - "80:3000"
    volumes:
      - discourse_data:/bitnami/discourse
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      - DISCOURSE_HOST=${DISCOURSE_HOST}
      - DISCOURSE_USERNAME=${DISCOURSE_ADMIN_USER}
      - DISCOURSE_PASSWORD=${DISCOURSE_ADMIN_PASSWORD}
      - DISCOURSE_EMAIL=${DISCOURSE_ADMIN_EMAIL}
      - DISCOURSE_SITE_NAME=${DISCOURSE_SITE_NAME:-Mein Forum}
      - DISCOURSE_DATABASE_HOST=postgresql
      - DISCOURSE_DATABASE_PORT_NUMBER=5432
      - DISCOURSE_DATABASE_USER=bn_discourse
      - DISCOURSE_DATABASE_NAME=bitnami_discourse
      - DISCOURSE_DATABASE_PASSWORD=${DB_PASSWORD}
      - DISCOURSE_REDIS_HOST=redis
      - DISCOURSE_REDIS_PORT_NUMBER=6379
      - DISCOURSE_REDIS_PASSWORD=${REDIS_PASSWORD}
      - POSTGRESQL_CLIENT_POSTGRES_USER=postgres
      - POSTGRESQL_CLIENT_POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRESQL_CLIENT_CREATE_DATABASE_NAME=bitnami_discourse
      - POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS=hstore,pg_trgm,vector
      - DISCOURSE_SMTP_HOST=${SMTP_HOST}
      - DISCOURSE_SMTP_PORT_NUMBER=${SMTP_PORT:-587}
      - DISCOURSE_SMTP_USER=${SMTP_USER}
      - DISCOURSE_SMTP_PASSWORD=${SMTP_PASSWORD}
      - DISCOURSE_SMTP_PROTOCOL=${SMTP_PROTOCOL:-tls}

  sidekiq:
    image: docker.io/bitnami/discourse:2026
    restart: unless-stopped
    depends_on:
      - discourse
    volumes:
      - discourse_data:/bitnami/discourse
    command: /opt/bitnami/scripts/discourse-sidekiq/run.sh
    environment:
      - DISCOURSE_HOST=${DISCOURSE_HOST}
      - DISCOURSE_DATABASE_HOST=postgresql
      - DISCOURSE_DATABASE_PORT_NUMBER=5432
      - DISCOURSE_DATABASE_USER=bn_discourse
      - DISCOURSE_DATABASE_NAME=bitnami_discourse
      - DISCOURSE_DATABASE_PASSWORD=${DB_PASSWORD}
      - DISCOURSE_REDIS_HOST=redis
      - DISCOURSE_REDIS_PORT_NUMBER=6379
      - DISCOURSE_REDIS_PASSWORD=${REDIS_PASSWORD}
      - DISCOURSE_SMTP_HOST=${SMTP_HOST}
      - DISCOURSE_SMTP_PORT_NUMBER=${SMTP_PORT:-587}
      - DISCOURSE_SMTP_USER=${SMTP_USER}
      - DISCOURSE_SMTP_PASSWORD=${SMTP_PASSWORD}

volumes:
  postgresql_data:
    driver: local
  redis_data:
    driver: local
  discourse_data:
    driver: local

Drei Punkte verdienen besondere Aufmerksamkeit: Erstens erzwingt depends_on mit condition: service_healthy, dass Discourse erst startet, wenn PostgreSQL und Redis wirklich bereit sind – ohne Healthcheck käme es zu ActiveRecord::NoDatabaseError-Fehlern beim Bootstrap. Zweitens werden die drei PostgreSQL-Extensions hstore, pg_trgm und vector automatisch beim ersten Start angelegt; fehlen sie, bricht der Discourse-Bootstrap mit einem Datenbankfehler ab. Drittens teilen discourse und sidekiq das Volume discourse_data – das ist kein Zufall, sondern technische Notwendigkeit.

Verifizieren: Die Syntax der Compose-Datei ist fehlerfrei.

docker compose -f /opt/discourse/compose.yaml config --quiet
# Keine Ausgabe = keine Syntaxfehler

Schritt 4: Stack starten und Bootstrap abwarten

Starte jetzt alle vier Container im Hintergrund. Docker lädt zuerst die Images herunter (ca. 1–2 GB), dann startet der Bootstrap-Prozess.

cd /opt/discourse
docker compose up -d

Der erste Start ist ungewöhnlich lang: Discourse führt Datenbankmigrationen durch, kompiliert Assets und legt den Admin-Account an. Das dauert je nach Hardware 5 bis 15 Minuten. Beobachte den Fortschritt live:

docker compose logs -f discourse

Warte, bis du in den Logs die Meldung Discourse is ready siehst. Erst dann ist das Forum erreichbar. Vorher antwortet der Webserver noch nicht auf HTTP-Anfragen.

Verifizieren: Alle vier Container laufen und sind „healthy" oder „running".

docker compose ps
# Erwartete Ausgabe (gekürzt):
# NAME          IMAGE                          STATUS
# discourse     bitnami/discourse:2026         Up (healthy)
# sidekiq       bitnami/discourse:2026         Up
# postgresql    bitnami/postgresql:latest      Up (healthy)
# redis         bitnami/redis:latest           Up (healthy)

curl -I http://localhost/
# Erwartete Ausgabe: HTTP/1.1 200 OK  (oder 302 Redirect)

Schritt 5: Erst-Einrichtung im Browser abschließen

Öffne http://forum.beispiel.de im Browser (oder vorerst http://<server-ip> für einen lokalen Test). Discourse begrüßt dich mit einem Setup-Wizard, der durch die grundlegende Konfiguration führt.

Melde dich mit den in der .env gesetzten Admin-Zugangsdaten an (DISCOURSE_ADMIN_USER / DISCOURSE_ADMIN_PASSWORD). Der Wizard fragt nach:

  1. Forenname und Beschreibung
  2. Erste Kategorien (du kannst das später im Admin-Panel unter /admin/categories anpassen)
  3. Sprache der Oberfläche (Deutsch ist als Plugin verfügbar: discourse-locale-de)
  4. E-Mail-Testversand – schicke eine Test-E-Mail, bevor du den Wizard abschließt

Das Admin-Panel erreichst du jederzeit unter /admin. Dort findest du auch die Einstellungen für Discourse Connect (SSO), Plugin-Verwaltung und alle Site-Settings.

Verifizieren: Der Setup-Wizard ist abgeschlossen, du siehst die Discourse-Startseite und hast eine Test-E-Mail erhalten.

docker compose logs discourse | grep -i "mail\|smtp\|email"
# Keine Fehler-Zeilen sollten auftauchen

Schritt 6: Reverse Proxy und HTTPS einrichten

Für den Produktivbetrieb ist HTTPS Pflicht – ohne TLS setzen Browser keine Secure-Cookies, und einige Discourse-Features (Web-Push-Benachrichtigungen, Service Worker) sind auf HTTPS angewiesen. Ändere dafür in der compose.yaml den Port-Eintrag, so dass Discourse nicht mehr direkt auf Port 80 lauscht, sondern nur noch intern erreichbar ist:

    ports:
      - "127.0.0.1:3000:3000"

Dann stellst du einen Reverse Proxy davor. Eine ausführliche Anleitung für Caddy mit automatischem HTTPS findest du unter Caddy als Reverse Proxy mit automatischem HTTPS. Alternativ funktioniert Traefik als Docker-Reverse-Proxy sehr gut, wenn mehrere Docker-Dienste auf demselben Host laufen.

Ein minimales Caddyfile für Discourse sieht so aus:

forum.beispiel.de {
    reverse_proxy localhost:3000
}

Caddy holt das Let's-Encrypt-Zertifikat vollautomatisch. Nach dem Proxy-Wechsel muss DISCOURSE_HOST in der .env weiterhin auf den öffentlichen Domainnamen zeigen – Discourse generiert daraus alle internen Links.

Verifizieren: HTTPS-Verbindung und korrektes Zertifikat.

curl -I https://forum.beispiel.de/
# Erwartete Ausgabe: HTTP/2 200 (oder 302)
# Kein SSL-Fehler, Zertifikat von Let's Encrypt

Schritt 7: Updates und Backups

Für Versionsupdates genügt es, den Image-Tag in der compose.yaml zu aktualisieren (z. B. von 2026 auf 2027), dann den neuen Stand zu pullen und die Container neu zu starten. Datenbankmigrationen laufen beim nächsten Start automatisch. Lege vor jedem Update ein Backup an. Wie du PostgreSQL-Backups per pg_dump automatisierst und in die Cloud synchronisierst, erklärt die Anleitung zu automatisierten PostgreSQL-Backups.

# Update durchführen (nach Backup!)
cd /opt/discourse
docker compose pull
docker compose up -d
# PostgreSQL-Dump aus dem laufenden Container
docker compose exec postgresql pg_dump \
  -U bn_discourse bitnami_discourse > /opt/backups/discourse_$(date +%Y%m%d).sql

# Discourse-Volume-Snapshot (Uploads, Assets)
docker run --rm \
  -v discourse_discourse_data:/data \
  -v /opt/backups:/backup \
  alpine tar czf /backup/discourse_data_$(date +%Y%m%d).tar.gz /data

Verifizieren: Neue Images wurden heruntergeladen, Container laufen mit aktualisierten Images.

docker compose ps
docker compose logs --tail=50 discourse
# Keine Fehler nach dem Update, Discourse antwortet auf HTTP

Eckdaten auf einen Blick

ParameterWert
Image (Web + Sidekiq)docker.io/bitnami/discourse:2026
Image (Datenbank)docker.io/bitnami/postgresql:latest
Image (Cache)docker.io/bitnami/redis:latest
Port (HTTP)80 → Container 3000
Volume Discoursediscourse_data:/bitnami/discourse
Volume PostgreSQLpostgresql_data:/bitnami/postgresql
Volume Redisredis_data:/bitnami/redis
Min. RAM1 GB (mit Swap), empfohlen 2 GB
Bootstrap-Dauer5–15 Minuten (erster Start)
Env-VariablePflichtBeispielwert
DISCOURSE_HOSTjaforum.beispiel.de
DISCOURSE_USERNAMEjaadmin
DISCOURSE_PASSWORDjamind. 10 Zeichen
DISCOURSE_EMAILjaadmin@beispiel.de
DISCOURSE_SMTP_HOSTjasmtp.mailgun.org
DISCOURSE_DATABASE_PASSWORDjasicheres Passwort
POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONSjahstore,pg_trgm,vector
ALLOW_EMPTY_PASSWORDneinnur lokal, nie Produktion

Troubleshooting / Typische Fehler

  1. ActiveRecord::NoDatabaseError oder PG::ConnectionBad im Discourse-Log: Discourse hat gestartet, bevor PostgreSQL bereit war. Ursache: depends_on ohne condition: service_healthy. Prüfe, ob Healthcheck und Bedingung gesetzt sind. Dann: docker compose down && docker compose up -d.
  2. Bootstrap bricht mit extension "hstore" does not exist ab: Die PostgreSQL-Extensions wurden beim ersten Start nicht angelegt. Volumes löschen, POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS=hstore,pg_trgm,vector prüfen, dann: docker compose down -v && docker compose up -d.
  3. Forum nach 15 Minuten immer noch nicht erreichbar: Live-Log beobachten: docker compose logs -f discourse. Häufige Ursache: Passwort-Mismatch zwischen POSTGRESQL_PASSWORD im postgresql-Service und DISCOURSE_DATABASE_PASSWORD.
  4. E-Mails kommen nicht an / Registrierung schlägt fehl: SMTP-Konfiguration falsch. Prüfe: docker compose logs sidekiq | grep -i smtp. Teste SMTP-Zugangsdaten im Admin-Panel unter /admin/email.
  5. Sidekiq-Container crasht sofort: Das Volume discourse_data:/bitnami/discourse fehlt beim Sidekiq-Service. Ohne dieses Volume fehlt Sidekiq die Rails-Umgebung.
  6. Image-Pull schlägt fehl (unauthorized): Bitnami-Images wurden aus dem freien Docker Hub entfernt (Broadcom-Übernahme). Fallback: Image-Referenz auf ghcr.io/bitnami/discourse:2026 ändern.
  7. CSP-Fehler im Browser / Cookies nicht gesetzt: Discourse läuft ohne HTTPS. Richte Caddy oder Traefik mit TLS ein und stelle sicher, dass DISCOURSE_HOST dem öffentlichen Hostnamen entspricht.

Häufige Fragen

Kann ich das offizielle discourse/base-Image direkt per docker compose verwenden?

Nein. Das offizielle Image aus dem discourse/discourse_docker-Repository setzt einen proprietären Bash-Launcher (./launcher) mit eigenen YAML-Templates voraus. Ein direktes docker compose up ist nicht vorgesehen. Für einen plattformneutralen Compose-Workflow ist bitnami/discourse die richtige Wahl.

Wie richte ich SSO (Single Sign-On) mit einem externen Identity-Provider ein?

Discourse Connect (früher DiscourseSSO) konfigurierst du nach der Installation vollständig im Admin-Panel unter /admin/site_settings. Setze dort discourse_connect_url auf den SSO-Endpoint deines Providers und trage ein gemeinsames sso_secret ein. Kein Container-Neustart erforderlich.

Wie aktualisiere ich Discourse auf eine neue Version?

Ändere den Image-Tag in der compose.yaml (z. B. von 2026 auf 2027), dann: docker compose pull && docker compose up -d. Datenbankmigrationen laufen automatisch. Lege vor dem Update ein Backup der Volumes an.

Wie viel RAM benötigt Discourse mindestens?

Laut offizieller Discourse-Dokumentation sind 1 GB RAM mit Swap das absolute Minimum. Für produktiven Betrieb werden 2 GB empfohlen. Bedenke: PostgreSQL, Redis und Sidekiq laufen zusätzlich zum Discourse-Webprozess.

Wie installiere ich Plugins bei der Bitnami-Distribution?

Offizielle Plugins lassen sich direkt über das Admin-Panel unter /admin/plugins installieren. Für manuelle Plugin-Installation (z. B. Community-Plugins) muss ein eigenes Dockerfile auf Basis von bitnami/discourse erstellt werden, das das Plugin einbettet.

Was ist DISCOURSE_SKIP_BOOTSTRAP?

Diese Variable ist nützlich, wenn du eine bestehende Discourse-Datenbank importierst. Mit DISCOURSE_SKIP_BOOTSTRAP=yes überspringt der Container die initiale Admin-Account-Erstellung – die Werte für DISCOURSE_USERNAME, DISCOURSE_PASSWORD und DISCOURSE_EMAIL werden in diesem Fall ignoriert.

Fazit

Discourse ist technisch anspruchsvoller als ein einfaches PHP-Forum – vier Container, PostgreSQL-Extensions, zwingend SMTP, langer erster Bootstrap. Wer diese Punkte kennt und die Schritte dieser Anleitung sorgfältig umsetzt, bekommt dafür eine der ausgereiftesten Open-Source-Community-Plattformen überhaupt. Der Einsatz mit der Bitnami-Distribution über Docker Compose ist der sauberste plattformneutrale Weg: kein proprietärer Launcher, vollständige Kontrolle über alle Container, einfaches Update per docker compose pull. Für KMU-Supportportale, Entwickler-Communities und interne Wissensdatenbanken ist Discourse die Referenz – und mit dieser Anleitung läuft es auf deinem eigenen Server.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. Caddy als Reverse Proxy mit automatischem HTTPS einrichten
  3. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS
  4. MySQL & PostgreSQL Backup automatisieren mit cron, pg_dump und rclone
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only

Offizielle Quellen: Bitnami Discourse Container – GitHub README | discourse_docker – offizielles Discourse Docker-Repository (Launcher-basiert)