Coturn in Docker zu betreiben sieht einfach aus, bis der erste Anruf keine Verbindung aufbaut und Sie merken, dass der Container nie einen echten Weg für den Relay-Verkehr hatte. Das Image ist klein und die Einrichtung wirklich schnell, fünf Minuten, wenn nichts schiefgeht, aber fast jeder stößt beim ersten Versuch an dieselbe Wand: Das Standardnetzwerk von Docker und die Portanforderungen eines TURN-Servers vertragen sich nicht.
Hier finden Sie die tatsächlich funktionierende docker-compose.yml, die wichtigen Einstellungen in turnserver.conf und die eine Netzwerkentscheidung, die bestimmt, ob Ihr coturn-Docker-Container echte Anruflast verkraftet oder nur einen kurzen lokalen Test.
Kurze Antwort
Zum Abschnitt springen
Voraussetzungen
Bevor Sie beginnen
- Docker Engine und Docker Compose auf einem Linux-Host (das Host-Netzwerk, der Modus dieser Anleitung, ist eine reine Linux-Funktion von Docker und verhält sich unter Docker Desktop für Mac/Windows anders).
- Ein Server mit öffentlicher, statischer IP-Adresse. TURN-Relay funktioniert nicht hinter CGNAT oder mit einer wechselnden privaten Anschluss-IP.
- Ein Domainname, der auf diese IP zeigt, wenn Sie TLS (turns:) unterstützen wollen, plus ein Zertifikat dafür.
- Die Ports 3478 und 5349 (TCP und UDP) sowie Ihr gewählter Relay-Portbereich in der Host-Firewall und in jeder vorgeschalteten Cloud-Sicherheitsgruppe geöffnet.
Das offizielle coturn-Docker-Image
Das zu verwendende Image ist coturn/coturn auf Docker Hub, direkt vom coturn-Projekt gepflegt und nicht von einem Dritten. Es gibt eine Variante auf Debian-Basis und eine kleinere auf Alpine-Basis (Tags wie 4.14-alpine), und beide werden im Gleichschritt mit den coturn-Releases aktualisiert. Pinnen Sie in der Produktion einen bestimmten Tag; nutzen Sie nicht latest, nur um festzustellen, dass sich das Relay-Verhalten in derselben Woche wie ein Störfall geändert hat.
Das Image bietet drei Wege, den Server zu konfigurieren: eine eingebundene turnserver.conf, Kommandozeilenoptionen hinter dem Image-Namen oder eine kleine Gruppe von Umgebungsvariablen für die automatische IP-Erkennung. Bei der dritten Option stolpern die meisten, mehr dazu weiter unten.
Coturn Docker Compose: die Einrichtung
Hier ist eine docker-compose.yml, die wirklich funktioniert, nicht die abgespeckte Version, die nur die STUN-Seite abdeckt:
services:
coturn:
image: coturn/coturn:4.14-alpine
container_name: coturn
restart: unless-stopped
network_mode: host
volumes:
- ./turnserver.conf:/etc/coturn/turnserver.conf:ro
- ./certs:/etc/coturn/certs:ro
- coturn-data:/var/lib/coturn
volumes:
coturn-data: Zwei Dinge fallen auf. Es gibt keinen ports:-Block, und das ist kein Fehler: Das Host-Netzwerk macht ihn überflüssig, und Compose würde ihn ohnehin ignorieren. Und coturn-data ist ein benanntes Volume statt eines Bind-Mounts, denn unter /var/lib/coturn/ liegt nur flüchtiger Sitzungszustand, den Sie vom Host aus nicht einsehen müssen.
Starten Sie es wie gewohnt:
docker compose up -d
docker compose logs -f coturn turnserver.conf konfigurieren
Diese Datei erledigt die eigentliche Arbeit. Eine minimale, aber produktionstaugliche Version:
listening-port=3478
tls-listening-port=5349
min-port=49152
max-port=65535
external-ip=203.0.113.10
realm=turn.example.com
use-auth-secret
static-auth-secret=replace-this-with-a-long-random-string
cert=/etc/coturn/certs/fullchain.pem
pkey=/etc/coturn/certs/privkey.pem
no-cli
no-multicast-peers
log-file=stdout Einige dieser Einstellungen sind wichtiger, als sie aussehen:
- external-ip: Setzen Sie hier die tatsächliche öffentliche IP Ihres Servers ein, lassen Sie es nicht leer. Hinter NAT (das sind technisch die meisten Cloud-VMs, auch mit zugewiesener öffentlicher IP) muss man coturn sagen, welche Adresse es den Clients mitteilen soll, sonst kommen die Relay-Kandidaten mit der privaten IP zurück und nichts verbindet sich.
- realm: Das ist einer der Begriffe, nach denen direkt gesucht wird, und er ist einfach: nur eine Zeichenkette, meist Ihre Domain, die den Authentifizierungsbereich festlegt. Für TURN selbst muss das DNS nirgendwohin zeigen, für Ihr TLS-Zertifikat allerdings schon.
- use-auth-secret / static-auth-secret: Das ist der Mechanismus für Langzeit-Zugangsdaten (HMAC-basierte, zeitlich begrenzte Paare aus Benutzername und Passwort), derselbe Ansatz wie im Coturn-AMI für AWS von Meetrix. Er ist einfacher zu betreiben als eine statische Liste aus Benutzernamen und Passwörtern und braucht keine Datenbank.
- no-cli: Deaktiviert die Telnet-basierte Admin-CLI von coturn auf Port 5766. Es gibt keinen Grund, sie in einem Container offenzulegen, und sie eingeschaltet zu lassen, ist unnötige Angriffsfläche.
Umgebungsvariablen oder Konfigurationsdatei
Wenn Sie gezielt nach coturn-Docker-Umgebungsvariablen gesucht haben, um TURN_REALM oder Ähnliches zu setzen, hier die direkte Antwort: Das offizielle Image hat sie nicht. Es unterstützt nur vier Umgebungsvariablen, und alle betreffen die automatische IP-Erkennung, nicht das Verhalten von TURN:
| Variable | Zweck |
|---|---|
DETECT_EXTERNAL_IP | Erkennt beim Start automatisch die externe IPv4-Adresse des Containers |
DETECT_RELAY_IP | Erkennt automatisch die IPv4-Adresse für Relay-Zuweisungen |
DETECT_EXTERNAL_IPV6 | Wie oben, für IPv6 |
DETECT_RELAY_IPV6 | Wie oben, für IPv6-Relay |
Alles andere, Realm, static-auth-secret, TLS-Zertifikate, der Portbereich, muss über turnserver.conf oder eine Kommandozeilenoption gehen, die an docker run oder den Compose-Befehl angehängt wird. Wenn Sie einen Blogbeitrag oder eine Stack-Overflow-Antwort gesehen haben, in der eine Umgebungsvariable TURN_REALM= funktioniert, handelt es sich fast sicher um ein Drittanbieter-Image und nicht um das offizielle, und es lässt sich nicht übertragen, wenn Sie später das Image wechseln.
Warum das Host-Netzwerk wichtig ist
An diesem Punkt scheitern die meisten ersten Versuche, auch die aus Tutorials kopierten, die ihn auslassen. TURN braucht einen großen offenen UDP-Portbereich für Relay-Zuweisungen, standardmäßig 49152 bis 65535, über 16.000 Ports. Der normale Weg von Docker, Ports freizugeben, ein -p-Flag oder ein ports:-Block pro Port, startet für jeden einen eigenen docker-proxy-Prozess im Userspace. Sechzehntausend davon zwingen einen Host in die Knie, lange bevor echter Verkehr ankommt.
network_mode: host umgeht das Problem vollständig: Der Container teilt direkt den Netzwerkstack des Hosts, ohne NAT, ohne Proxy pro Port und ohne Übersetzungsschicht, mit der coturn kämpfen müsste, wenn es seine eigene externe IP ermitteln will.
Wenn Sie kein Host-Netzwerk nutzen können
Noch etwas, das Sie vor dem Deployment wissen sollten: Ein coturn-Issue auf GitHub (#966) dokumentiert genau dieses Problem, das sich als Anrufe zeigt, die sich verbinden und dann abbrechen, mit „allocation watchdog determined stale session state“ in den Logs, zurückzuführen darauf, dass der Container unter Host-Netzwerk die falsche externe IP errät. Wenn Sie external-ip ausdrücklich setzen, wie in der Konfiguration oben, vermeiden Sie das.
Den Container testen
Sobald der Container läuft, erzeugen Sie einen temporären Benutzernamen und ein Passwort anhand Ihres static-auth-secret:
secret=replace-this-with-a-long-random-string && \
time=$(date +%s) && \
expiry=86400 && \
username=$(( $time + $expiry )) && \
echo username:$username && \
echo password:$(echo -n $username | openssl dgst -binary -sha1 -hmac $secret | openssl base64) Tragen Sie dann Serveradresse, erzeugten Benutzernamen und Passwort in das Testtool Trickle ICE ein, sammeln Sie die Kandidaten und suchen Sie in den Ergebnissen nach einem Relay-Kandidaten. Kein Relay-Kandidat heißt, dass der Container zwar läuft, aber noch nicht als TURN-Server nutzbar ist, meist ein Problem mit external-ip, der Firewall oder dem Portbereich und nicht mit coturn selbst. Unser WebRTC-ICE-Tester führt dieselbe Prüfung aus und erklärt jeden gefundenen Kandidaten in verständlicher Sprache.
Fehlerbehebung
- Der Container startet, aber kein Relay-Kandidat erscheint: Prüfen Sie, ob
external-ipin turnserver.conf mit der tatsächlichen öffentlichen IP des Servers übereinstimmt, und stellen Sie sicher, dass die vorgeschaltete Sicherheitsgruppe oder Firewall den gesamten UDP-Bereich von min-port bis max-port erlaubt, nicht nur 3478 und 5349. - Funktioniert lokal, scheitert für entfernte Nutzer: Fast immer eine Lücke in Firewall oder Sicherheitsgruppe beim Relay-Portbereich, oder der Container läuft ohne Host-Netzwerk mit nur 3478/5349 veröffentlicht.
- TLS-Handshake auf 5349 schlägt fehl: Der Mount-Pfad des Zertifikat-Volumes muss genau dem entsprechen, worauf
certundpkeyim Container zeigen. Ein Tippfehler in einem relativen Pfad scheitert hier lautlos in den Logs, wenn Sie nicht genau hinsehen. - Hohe CPU-Last unter Last: Wenn Sie kein Host-Netzwerk nutzen, ist das sehr oft der oben beschriebene docker-proxy-Overhead und nicht coturn selbst, das zu kämpfen hat.
Wann Sie die Eigeninstallation überspringen
Coturn in Docker zu betreiben ist die richtige Wahl, wenn Sie volle Kontrolle über die Konfiguration wollen, ohnehin einen Docker-basierten Stack betreiben oder testen, bevor Sie sich auf eine Infrastruktur festlegen. Es ist aber auch ein weiterer Dienst, der jetzt Ihnen gehört: das Image patchen, Festplatte und Speicher überwachen, Zertifikate erneuern und derjenige sein, der alarmiert wird, wenn eine Netzwerkänderung, von der Ihnen niemand erzählt hat, den Relay-Portbereich blockiert.
Wenn Sie diese Bereitschaft lieber nicht selbst übernehmen, pflegt Meetrix ein vorkonfiguriertes Coturn-AMI für AWS und ein passendes Image für GCP, beide mit Netzwerk, TLS und Langzeit-Zugangsdaten von Haus aus korrekt eingerichtet. Es gibt auch eine Bereitstellung mit einem Klick, wenn Sie die Kostenvorteile des Selbsthostings wollen, ohne je eine docker-compose.yml anzufassen. Und wenn der TURN-Server speziell für eine Jitsi-Meet-Bereitstellung gedacht ist, behandeln die Anleitung zur TURN-Einrichtung für Jitsi und die Jitsi-Anleitung für AWS (oder ihr GCP-Gegenstück) die Konfigurationsunterschiede, die dort konkret auftreten.
Häufig gestellte Fragen
Was ist das offizielle Docker-Image von coturn?
Es ist coturn/coturn auf Docker Hub, gepflegt vom coturn-Projekt selbst. Es gibt Varianten auf Basis von Debian und von Alpine (die alpine-Tags sind deutlich kleiner). Images von Drittanbietern wie instrumentisto/coturn existieren auch, aber das offizielle Image ist die erste Wahl.
Unterstützt das coturn-Docker-Image Umgebungsvariablen wie TURN_REALM?
Nein. Das offizielle Image bietet nur eine Handvoll Umgebungsvariablen für die automatische IP-Erkennung (DETECT_EXTERNAL_IP, DETECT_RELAY_IP und ihre IPv6-Entsprechungen). Realm, static-auth-secret und jede andere TURN-Einstellung kommen aus einer eingebundenen turnserver.conf oder aus Kommandozeilenoptionen, nicht aus Umgebungsvariablen.
Warum braucht coturn in Docker network_mode: host?
Coturn leitet Medien über einen großen UDP-Portbereich weiter, standardmäßig 49152 bis 65535. Diesen ganzen Bereich mit der normalen Portfreigabe von Docker zu veröffentlichen, startet einen docker-proxy-Prozess pro Port, was den Host unter echter Anruflast in die Knie zwingt. Das Host-Netzwerk umgeht diese Schicht vollständig.
Kann ich coturn in Docker ohne Host-Netzwerk betreiben?
Ja, wenn Sie vorher den Relay-Bereich verkleinern. Setzen Sie min-port und max-port in turnserver.conf auf etwa 49152 bis 49352 und veröffentlichen Sie diesen kleineren Bereich plus 3478 und 5349 in Ihrer Compose-Datei. Das funktioniert, begrenzt aber, wie viele weitergeleitete Anrufe der Server gleichzeitig bewältigen kann.
Wie erzeuge ich TURN-Zugangsdaten, um einen coturn-Container zu testen?
Mit use-auth-secret und einem in turnserver.conf gesetzten static-auth-secret erzeugen Sie per HMAC-SHA1-Skript (openssl dgst -hmac) einen zeitlich begrenzten Benutzernamen und ein Passwort und testen diese dann mit dem WebRTC-Tool Trickle ICE gegen den Container, bevor Sie ihn in Ihre Anwendung einbinden.
Wo speichert coturn in Docker seine Daten?
Das Image schreibt standardmäßig nach /var/lib/coturn/, vor allem SQLite-Zustand für den turnserver-Prozess. Wenn Sie nur Langzeit-Zugangsdaten über static-auth-secret statt einer Benutzerdatenbank verwenden, können Sie diesen Pfad als tmpfs einbinden, da es nichts gibt, was einen Neustart überdauern müsste.
Die Docker-Einrichtung ganz überspringen
Starten Sie einen vorkonfigurierten coturn-Server auf AWS, bei dem Netzwerk, TLS und Zugangsdaten bereits korrekt eingerichtet sind.
Coturn im AWS Marketplace holen