Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 23.09.2026 · 11 min Lesezeit Geprüft 02.11.2026

Traccar mit Docker Compose selbst hosten: GPS-Tracking-Server im Eigenbetrieb

Traccar empfängt Positionsdaten von GPS-Trackern und zeigt sie auf der Karte. Diese Anleitung zeigt Installation mit Docker Compose, gültige traccar.xml, erstes Konto, sichere Geräteports, Reverse Proxy, Backup und Update für Traccar 6.16.

Werbung Mit * 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

Titelbild: Traccar mit Docker Compose, GPS, Geräte, Karten

Traccar ist ein quelloffener GPS-Tracking-Server (Apache-2.0). Er nimmt Positionsmeldungen von Fahrzeug- und Asset-Trackern sowie Smartphone-Apps entgegen, speichert die Historie und zeigt sie in einer Weboberfläche auf der Karte, mit Geofences, Berichten und Benachrichtigungen. Diese Anleitung zeigt die Installation mit Docker Compose, den Funktionscheck, die sichere Freigabe der Geräteports, Backup und Update.

Voraussetzungen

  • Linux-Server (x86-64 oder ARM64) mit Docker Engine und Compose-Plugin; docker compose version muss antworten.
  • Für einen kleinen Betrieb mit wenigen Geräten genügen 2 CPU-Kerne, 2 bis 4 GB RAM und 10 GB freier Speicher. Traccar ist ein Java-Dienst; die JVM steckt im Image (im Test JVM 25.0.4.1), auf dem Host brauchen Sie kein Java.
  • Root- oder sudo-Rechte, eine Domain mit DNS-Eintrag für den Zugriff von außen und einen Reverse Proxy mit TLS, etwa Caddy.
  • Freie Ports: 8082/TCP lokal für die Weboberfläche, dazu je eingesetztem Gerätemodell ein Protokoll-Port ab 5000 (TCP und UDP).
  • Datenschutz vorab geklärt: Standortdaten von Mitarbeitenden sind personenbezogene Daten. Zweck, Speicherdauer, Zugriffsrechte und gegebenenfalls die Beteiligung des Betriebsrats gehören vor die Inbetriebnahme. Dieser Beitrag ist keine Rechtsberatung.
EckdatenWert
Imagetraccar/traccar:6.17.0-alpine (Docker Hub, auch Debian- und Ubuntu-Varianten, amd64 und arm64)
Weboberfläche8082/TCP, hier nur an 127.0.0.1
Geräteport im Beispiel5055/TCP und 5055/UDP (Traccar-Client, OsmAnd-Protokoll)
Volumes./data, ./logs, ./traccar.xml (nur lesend)
DatenbankH2 eingebaut (Start), MySQL oder TimescaleDB für Produktion
Startzeit im TestWeboberfläche je nach Hardware nach 10 s bis rund einer Minute

Schritt 1: Verzeichnisse und Konfiguration anlegen

Traccar liest seine Einstellungen aus /opt/traccar/conf/traccar.xml, einer XML-Properties-Datei. Existiert die Datei beim ersten Start nicht, legt Docker an ihrer Stelle ein Verzeichnis an. Eine leere Datei reicht ebenfalls nicht: Im Nachtest mit 6.16.0 brach Traccar damit ab. Die folgende Minimal-Konfiguration entspricht der Vorlage setup/traccar.xml aus dem Projekt (H2-Datenbank im Datenordner) und startete im Test sauber.

sudo mkdir -p /opt/traccar/logs /opt/traccar/data
sudo tee /opt/traccar/traccar.xml >/dev/null <<'XML'
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE properties SYSTEM 'http://java.sun.com/dtd/properties.dtd'>
<properties>
    <entry key='database.driver'>org.h2.Driver</entry>
    <entry key='database.url'>jdbc:h2:./data/database</entry>
    <entry key='database.user'>sa</entry>
    <entry key='database.password'></entry>
</properties>
XML
cd /opt/traccar

ls -la /opt/traccar zeigt traccar.xml als Datei (Zeile beginnt mit -, nicht mit d), und head -3 /opt/traccar/traccar.xml gibt die XML-Kopfzeilen aus.

Schritt 2: compose.yaml erstellen

Die offizielle Dokumentation startet Traccar per docker run und veröffentlicht dabei die Weboberfläche auf Port 80 sowie den kompletten Bereich 5000 bis 5300 für TCP und UDP. Das ist bequem, hat aber einen Preis: Laut Dokumentation startet Docker dann für jeden einzelnen Port einen eigenen docker-proxy-Prozess, getrennt nach TCP und UDP. Das kostet viel Arbeitsspeicher und kann unter Last Verbindungen lecken. Die Compose-Datei unten veröffentlicht deshalb nur, was gebraucht wird. Legen Sie /opt/traccar/compose.yaml an:

services:
  traccar:
    image: traccar/traccar:6.17.0-alpine
    container_name: traccar
    hostname: traccar
    restart: unless-stopped
    ports:
      # Weboberflaeche nur lokal, oeffentlich ueber den Reverse Proxy
      - "127.0.0.1:8082:8082"
      # Nur die Protokoll-Ports der tatsaechlich genutzten Geraete
      - "5055:5055"
      - "5055:5055/udp"
    volumes:
      - ./logs:/opt/traccar/logs:rw
      - ./data:/opt/traccar/data:rw
      - ./traccar.xml:/opt/traccar/conf/traccar.xml:ro
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8082/api/server || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 120s

Zu den Parametern: Der feste Patchstand statt latest sorgt dafür, dass ein Update eine bewusste Entscheidung bleibt. Port 5055 ist der Port des Traccar-Client-Protokolls; welche Nummer Ihr Tracker braucht, steht in der Protokollliste auf traccar.org. Die Mounts entsprechen den Empfehlungen der Docker-Dokumentation. Der Healthcheck nutzt BusyBox-wget, das im Alpine-Image vorhanden ist (im Nachtest bestätigt); bei der Debian- oder Ubuntu-Variante prüfen Sie vorher, ob wget oder curl enthalten ist. Die start_period von 120 Sekunden berücksichtigt die gemessene Startzeit.

Alternativ schaltet die Dokumentation den Userland-Proxy ab ("userland-proxy": false in /etc/docker/daemon.json), damit Docker iptables-NAT nutzt. Diese Einstellung gilt für den gesamten Docker-Daemon und alle Container auf dem Host. Nach einer frischen Installation von Docker CE existiert die Datei nicht (im Test so vorgefunden); dann legen Sie sie wie unten gezeigt an. Besteht sie bereits, ergänzen Sie nur den Schlüssel, statt die Datei zu überschreiben. Der Neustart des Daemons beendet alle Container kurz, Dienste mit restart: unless-stopped starten danach von selbst wieder. Im Test liefen danach keine docker-proxy-Prozesse mehr, die Ports leitete Docker per iptables-DNAT weiter, und die Bindung von 8082 an 127.0.0.1 blieb erhalten. Nutzen Sie den Schalter nur, wenn Sie wirklich viele unterschiedliche Gerätemodelle betreiben.

# nur, wenn /etc/docker/daemon.json noch nicht existiert
test -e /etc/docker/daemon.json || echo '{ "userland-proxy": false }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
pgrep -c docker-proxy

sudo docker compose config --quiet endet ohne Ausgabe und mit Exit-Code 0.

Schritt 3: Starten und Funktion prüfen

cd /opt/traccar
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f traccar

Rechnen Sie mit einer kurzen Wartezeit. In den Tests antwortete die Weboberfläche je nach Hardware nach 10 Sekunden bis rund einer Minute. Im Log erscheint dann eine Zeile mit Started oejs.ServerConnector und 0.0.0.0:8082 (im Test Jetty 12.1.13). Beenden Sie die Logansicht mit Strg+C und prüfen Sie Oberfläche und API:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/
curl -s http://127.0.0.1:8082/api/server | head -c 400

Der Endpunkt /api/server liefert ohne Anmeldung JSON mit Version und Registrierungsstatus. Er belegt, dass JVM, Webserver und Konfiguration geladen sind, und eignet sich als Monitoring-Check. Im Test antwortete /api/session ohne Sitzung dagegen mit HTTP 404, nicht mit 401. Ein Check, der dort auf 401 wartet, meldet also falsch.

sudo docker compose ps zeigt den Dienst nach spätestens zwei Minuten als healthy, der erste curl gibt 200 aus, und die API-Antwort enthält "version":"6.17.0".

Schritt 4: Erstes Konto anlegen

Es gibt keine Standardzugangsdaten. Ein Login-Versuch mit admin/admin wurde im Test mit HTTP 401 beantwortet. Das erste Konto legen Sie über die Registrierung der Weboberfläche an. Solange noch kein Benutzer existiert, meldet /api/server "newServer":true, und die Oberfläche leitet direkt auf die Registrierung weiter. Im Test erhielt das erste Konto automatisch Administratorrechte, obwohl /api/server "registration":false meldete. Diese Einstellung gilt erst für weitere Konten: Ein zweiter Registrierungsversuch wurde mit HTTP 400 abgelehnt. Das entspricht dem Quellcode (UserResource, Version 6.16.0).

Da die Oberfläche nur lokal gebunden ist, öffnen Sie sie vor der Proxy-Einrichtung über einen SSH-Tunnel von Ihrem Arbeitsplatz aus und rufen dann im Browser http://localhost:8082 auf:

ssh -L 8082:127.0.0.1:8082 admin@ihr-server.example.com

Registrieren Sie das Administratorkonto mit einem starken Passwort. Legen Sie für weitere Personen eigene Konten mit eingeschränkter Gerätesicht an, statt Zugangsdaten zu teilen.

Traccar-Registrierungsformular mit den Feldern Name, Email und Passwort sowie der Schaltfläche Registrieren
Auf einem leeren Server öffnet Traccar automatisch die Registrierung für das erste Konto.
Traccar-Einstellungen mit Menü links, unten die Administratoreinträge Ankündigung und Server
Nach der Anmeldung als Administrator erscheinen in den Einstellungen die Einträge Ankündigung und Server.

Die Anmeldung mit dem neuen Konto gelingt, und unter den Einstellungen ist der Bereich „Server“ sichtbar, der nur Administratoren angezeigt wird.

Schritt 5: Firewall und Reverse Proxy einrichten

Hier unterscheidet sich Traccar von einer gewöhnlichen Webanwendung. Der Reverse Proxy bedient nur die Weboberfläche und die REST-API auf Port 8082. Die Geräteports laufen nicht über den HTTP-Proxy, denn viele Tracker sprechen binäre TCP- oder UDP-Protokolle. Diese Ports gehen direkt an den Container und brauchen eigene Firewallregeln, TCP und UDP getrennt. Kommen die Tracker aus bekannten Netzen, schränken Sie die Freigabe zusätzlich per Quell-IP ein.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 5055/tcp
sudo ufw allow 5055/udp
sudo ufw status numbered

Docker schreibt für veröffentlichte Ports eigene iptables-Regeln, die ufw je nach Konfiguration umgehen können. Prüfen Sie die Erreichbarkeit deshalb immer von außen. Für TLS verweist die Traccar-Dokumentation auf Caddy; ein minimaler Caddyfile-Block genügt:

traccar.example.com {
    reverse_proxy 127.0.0.1:8082
}

curl -I https://traccar.example.com liefert von einem anderen Rechner aus HTTP 200 mit gültigem Zertifikat, curl -m 5 http://IHRE-SERVER-IP:8082/ scheitert dagegen, und ein Testgerät oder die Traccar-Client-App meldet eine Position, die auf der Karte erscheint.

Traccar-Kartenansicht mit einem Gerät im Status Online in der Liste links und seinem Marker auf der Karte
Ein Testgerät hat über Port 5055 eine Position gemeldet und erscheint als online auf der Karte.

Schritt 6: Backup und Wiederherstellung

Alle Nutzdaten liegen in ./data. Nach dem ersten Start fanden sich dort im Test database.mv.db und database.trace.db, beide im Besitz von root. Ein tar oder rm ohne sudo scheitert deshalb mit „Permission denied“. Eine Kopie der laufenden H2-Datei kann inkonsistent sein, sichern Sie daher im gestoppten Zustand:

cd /opt/traccar
sudo docker compose stop
sudo tar czf /var/backups/traccar-$(date +%F).tar.gz data traccar.xml compose.yaml
sudo docker compose start

Mit MySQL oder PostgreSQL sichern Sie stattdessen einen Dump per mysqldump beziehungsweise pg_dump aus dem Datenbankcontainer, das geht im laufenden Betrieb. Die traccar.xml gehört in jedem Fall ins Backup. Zum Wiederherstellen stoppen Sie den Stack, legen den alten Datenordner beiseite und spielen das Archiv als root zurück, damit die Eigentümer erhalten bleiben:

cd /opt/traccar
sudo docker compose down
sudo mv data data.alt
sudo tar xzf /var/backups/traccar-JJJJ-MM-TT.tar.gz -C /opt/traccar
sudo docker compose up -d

Üben Sie den Restore einmal auf einem Zweitsystem, bevor Sie sich im Ernstfall darauf verlassen.

sudo tar tzf /var/backups/traccar-$(date +%F).tar.gz listet data/database.mv.db, traccar.xml und compose.yaml; nach einem Restore zeigt die Weboberfläche Ihre Geräte und Positionen.

Schritt 7: Update durchführen

Traccar migriert das Datenbankschema beim Start. Eine migrierte Datenbank läuft nicht mit einem älteren Image weiter; das Zurücksetzen des Tags allein ist also kein Rollback. Ein belastbarer Rückweg besteht aus altem Image-Tag plus vorher gesicherter Datenbank. Lesen Sie vor jedem Sprung die Release Notes.

cd /opt/traccar
# 1. Backup wie in Schritt 6
# 2. Image-Tag in compose.yaml auf die neue Version setzen
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f traccar

Für den Sprung von 6.15 auf 6.16 nennt das Projekt keine Breaking Changes; 6.16 bringt unter anderem ein Ereignis für das Überqueren von Geofences, überarbeitete Kraftstoffberichte und ein überarbeitetes GL200-Protokoll. Wer bisher eine leere traccar.xml eingebunden hat, ersetzt sie vor dem Update durch die Minimal-Konfiguration aus Schritt 1.

Update von 6.16 auf 6.17: Breaking Changes nennt das Projekt auch hier nicht. 6.17 ergänzt laut Ankündigung unter anderem eine Karte im Diagrammbericht, Geschäftsfahrten, Attribute für Elektrofahrzeuge, Zündungsdaten in der neuen Fahrtenberechnung, das Teltonika-Iridium-Protokoll und mehrere Sicherheitskorrekturen. Protokoll-Ports lassen sich jetzt dynamisch in den Einstellungen verwalten, und die Weboberfläche kann unter einem Unterpfad laufen. Veröffentlicht werden weiterhin nur die Ports aus der compose.yaml: Wer in den Einstellungen einen weiteren Protokoll-Port aktiviert, muss ihn dort zusätzlich eintragen. Im Test mit dieser Anleitung startete 6.17.0-alpine auf der Datenbank von 6.16.0 ohne Eingriff und wurde healthy; /api/server meldete "version":"6.17.0", Konto, Gerät und gespeicherte Position blieben erhalten, eine neue OsmAnd-Meldung auf Port 5055 wurde mit 200 angenommen, ein falsches Passwort gab 401 und eine zweite Registrierung weiter 400.

curl -s http://127.0.0.1:8082/api/server meldet die neue Version, sudo docker compose ps zeigt healthy, und vorhandene Geräte samt Historie sind in der Oberfläche sichtbar.

Grundlagen zum Betrieb finden Sie in Docker Compose unter Linux: Grundlage für Selfhosting und Docker Compose absichern: Secrets, Healthchecks, Non-Root.

Typische Fehler

FehlerbildUrsacheLösung
Weboberfläche antwortet direkt nach dem Start nicht, curl meldet 000JVM startet noch; im Test 10 s bis rund eine MinuteWarten, erst nach zwei bis drei Minuten ins Log sehen
Container in Neustart-Schleife, Log zeigt SAXParseExceptionEingebundene traccar.xml leer oder kein gültiges XML (im Test mit 6.16.0 beobachtet)Minimal-Konfiguration aus Schritt 1 eintragen, Stack neu starten
traccar.xml ist ein VerzeichnisDatei fehlte beim ersten Start, Docker hat einen Ordner angelegtStack stoppen, Ordner entfernen, Datei anlegen, neu starten
Login mit admin/admin ergibt HTTP 401Keine StandardzugangsdatenErstes Konto über die Registrierung anlegen (Schritt 4)
Monitoring meldet dauerhaft Fehler/api/session liefert ohne Sitzung 404 statt 401Check auf /api/server umstellen
Sehr viele docker-proxy-Prozesse, hoher RAM-VerbrauchKompletter Bereich 5000 bis 5300 veröffentlichtNur genutzte Ports veröffentlichen
Gerät sendet, nichts kommt anPort fehlt in compose.yaml oder Firewall, TCP/UDP verwechseltPort und Protokoll prüfen; Geräteports laufen nicht über den Proxy
Backup scheitert mit „Permission denied“Dateien in data gehören rootBackup mit sudo oder als root-Cronjob
Portkonflikt beim StartPort bereits belegtsudo ss -tulpn | grep 8082, Dienst stoppen oder Host-Port ändern

Häufige Fragen

Reicht die eingebaute H2-Datenbank?

Für Tests und sehr kleine Installationen ja. Die offizielle Dokumentation rät für den Produktivbetrieb von H2 ab und empfiehlt MySQL für kleinere und TimescaleDB für große Installationen; für beide gibt es Compose-Beispiele des Projekts. Die Umstellung erfolgt über die Datenbankeinträge in traccar.xml. Als Host gehört dort der Compose-Servicename hinein, nicht localhost. Planen Sie den Wechsel als Neuaufsetzen mit Datenübernahme.

Ist Traccar ein Flottenmanagement?

Nein. Traccar verwaltet Positionen, Historie, Geofences, Berichte und Benachrichtigungen. Tourenplanung, Abrechnung oder Werkstattverwaltung fehlen; dafür lässt sich Traccar über seine REST-API als Datenlieferant anbinden.

Wie entfernen Sie Traccar vollständig?

Mit sudo docker compose down, sudo docker image rm traccar/traccar:6.17.0-alpine und sudo rm -rf /opt/traccar. Der letzte Befehl löscht alle Geräte, Benutzer und Positionen endgültig, legen Sie vorher ein Backup an. Entfernen Sie danach die ufw-Regeln, den Proxy-Eintrag und den DNS-Datensatz.

Fazit

Traccar läuft mit Docker Compose als einzelner Container und war in den Tests nach 10 Sekunden bis rund einer Minute einsatzbereit. Die Stolpersteine liegen in den Details: eine gültige traccar.xml vor dem ersten Start, nur die genutzten Geräteports öffnen, die Weboberfläche hinter einen Proxy mit TLS legen und die H2-Datei nur gestoppt sichern. Für den Dauerbetrieb mit mehreren Fahrzeugen lohnt der frühe Wechsel auf MySQL oder TimescaleDB, und die Datenschutzfragen klären Sie vor dem ersten Tracker.

Weiterführende Anleitungen und Quellen

TraccarDocker ComposeGPS-TrackingSelfhostingFlottenortungOpen Source