Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 05.10.2026 · 10 min Lesezeit

Mealie mit Docker Compose installieren, absichern und sichern

Diese Anleitung zeigt, wie Sie Mealie 3.28.0 mit Docker Compose und SQLite betreiben, das Standardkonto ersetzen, die Registrierung geschlossen halten, einen Reverse Proxy mit TLS davorsetzen und Rezepte per Mealie-Backup oder Datenarchiv sichern und wiederherstellen.

Geprüft am 05.10.2026 · für Mealie 3.28.0

Mit KI erstellt – redaktionelle Prüfung ausstehend

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

Startbild der Anleitung: Mealie mit Docker Compose installieren, absichern und sichern

Mealie ist eine Rezeptverwaltung für den eigenen Server: Rezepte importieren, ordnen, skalieren, daraus Einkaufslisten und einen Wochenplan machen. Das passt für Familien genauso wie für eine kleine Kantine oder einen Imbiss, in dem Rezepturen nicht in Chats und Zettelkästen verstreut liegen sollen. Diese Anleitung zeigt den Betrieb der Version 3.28.0 mit Docker Compose und SQLite: geschlossene Registrierung, geändertes Standardkonto, Reverse Proxy mit TLS sowie eine Sicherung, deren Wiederherstellung nachweislich funktioniert.

Voraussetzungen

Mealie ist genügsam, solange wenige Personen gleichzeitig arbeiten. Die Dokumentation nennt SQLite als ideale Wahl für 1 bis 20 Benutzer und empfiehlt für mehr gleichzeitige Nutzer PostgreSQL.

  • Linux-Server oder VM mit 1 bis 2 CPU-Kernen, 2 GB RAM und einigen GB freiem Speicher, mehr wächst nur mit Rezeptbildern
  • Architektur x86-64 oder ARM64, 32-Bit-ARM wird laut Dokumentation nicht unterstützt
  • Docker Engine mit Compose-Plugin (docker compose)
  • Für den Zugriff von außen eine Domain wie mealie.example.de und einen Reverse Proxy mit Zertifikat; im reinen Heimnetz genügt interner DNS

Grenzen: Mealie speichert Rezepte, keine Warenwirtschaft und keine HACCP-Dokumentation. SQLite gehört nicht auf ein Netzlaufwerk, die Dokumentation warnt vor Datenbanksperren und Beschädigung und rät dort zu PostgreSQL. Lizenz des Projekts ist AGPL-3.0.

Schritt 1: Projektordner, compose.yaml und .env anlegen

Legen Sie einen Ordner /opt/mealie mit dem Unterordner data an. Die Beispieldatei der offiziellen Dokumentation (docs.mealie.io, Installation mit SQLite) wurde hier um drei Dinge ergänzt: Der Port ist nur an 127.0.0.1 gebunden, damit nur der Reverse Proxy ihn erreicht, die Daten liegen in einem Bind-Mount statt in einem benannten Volume, und Zeitzone und Adresse kommen aus der .env.

services:
  mealie:
    image: ghcr.io/mealie-recipes/mealie:v3.28.0
    container_name: mealie
    restart: unless-stopped
    ports:
      - "127.0.0.1:9925:9000"
    deploy:
      resources:
        limits:
          memory: 1000M
    volumes:
      - ./data:/app/data
    environment:
      ALLOW_SIGNUP: "false"
      PUID: ${PUID}
      PGID: ${PGID}
      TZ: ${TZ}
      BASE_URL: ${BASE_URL}
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:9000/api/app/about')"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
PUID=1000
PGID=1000
TZ=Europe/Berlin
BASE_URL=https://mealie.example.de

Der Tag trägt das Präfix v. Ein Pull von ghcr.io/mealie-recipes/mealie:3.28.0 scheitert mit failed to resolve reference ... not found. Das Speicherlimit stammt aus der offiziellen Vorlage: Python reserviert auf großen Maschinen sonst mehr Arbeitsspeicher als nötig.

Verifizieren: docker compose config gibt die Datei ohne Fehler und mit eingesetzten Werten aus.

Schritt 2: Container starten und Healthcheck prüfen

cd /opt/mealie
sudo chown 1000:1000 data
docker compose up -d
docker compose ps
curl -s http://127.0.0.1:9925/api/app/about

Der erste Start legt Datenbank, Standardgruppe „Home“ und Standardhaushalt „Family“ an und führt Migrationen aus. Im Test antwortete die API nach knapp 20 Sekunden, davor lieferte curl den Code 000, das ist kein Fehler. Nach rund 30 Sekunden stand der Container auf healthy. Die Antwort enthält "version":"v3.28.0" und "allowSignup":false.

Der Container startet als root und wechselt laut Log mit Switching to dedicated user auf die UID aus PUID. Gehörte der Datenordner einer fremden UID (im Test 4242 mit Modus 700), setzte Mealie ihn selbst auf 1000:1000 um, der Dienst lief ohne Fehler. Anders beim direkten Start mit --user 1000:1000 auf einem root-eigenen Ordner: PermissionError: [Errno 13] Permission denied: '/app/data/groups'. Lassen Sie den Container deshalb über PUID und PGID den Benutzer wechseln und setzen Sie kein user: in der Compose-Datei.

Verifizieren: docker compose ps zeigt healthy, ls -ln data zeigt mealie.db, recipes und backups mit UID 1000.

Schritt 3: Standardkonto ändern und Registrierung prüfen

Mealie legt beim ersten Start einen Administrator mit der E-Mail changeme@example.com und dem Passwort MyPassword an. Solange das so bleibt, kann jeder im Netz mit dem Dienst arbeiten. Ändern Sie beides noch vor dem Reverse Proxy. Im Browser geht das nach der Anmeldung über das Benutzerprofil, per API so:

TOKEN=$(curl -s -X POST http://127.0.0.1:9925/api/auth/token \
  --data-urlencode "username=changeme@example.com" \
  --data-urlencode "password=MyPassword" | jq -r .access_token)
curl -s -X PUT http://127.0.0.1:9925/api/users/password \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"currentPassword":"MyPassword","newPassword":"EIN-LANGES-NEUES-PASSWORT"}'

Antwort: {"message":"Password updated","error":false}. Danach lieferte die Anmeldung mit dem alten Passwort 401, mit dem neuen 200. Ein vor der Änderung geholtes Token war anschließend ungültig (401 Could not validate credentials), Sie müssen sich also neu anmelden. Die E-Mail-Adresse ändern Sie unter Administration, Benutzer.

Anmeldeseite von Mealie mit Feldern für E-Mail oder Benutzername und Passwort sowie dem ausgegrauten Hinweis „Nur auf Einladung“
Anmeldeseite: Die Registrierung ist deaktiviert, der Link zeigt „Nur auf Einladung“.

Die Registrierung ist ab Mealie 1.4.0 standardmäßig geschlossen. Ein Versuch ohne Einladung endete mit 403 und User Registration is Disabled. Weitere Personen legen Sie als Administrator an oder laden sie per Token ein. Gegen Erraten von Passwörtern sperrt Mealie laut Dokumentation Konten nach 5 Fehlversuchen für 24 Stunden (SECURITY_MAX_LOGIN_ATTEMPTS, SECURITY_USER_LOCKOUT_TIME).

Verifizieren: Anmeldung mit changeme@example.com und MyPassword liefert 401, POST /api/users/register liefert 403.

Schritt 4: Rezepte anlegen und per URL importieren

Ein Rezept legen Sie in der Oberfläche über „Erstellen“ an. Der Import per URL liest strukturierte Daten (schema.org) einer Rezeptseite. Im Test klappte das mit zwei öffentlichen Rezeptseiten, Titel, Zutaten, Schritte und Bild landeten im Bestand. Eine URL ohne Rezeptdaten endete mit 400 und BAD_RECIPE_DATA. Ohne Internetzugang auf dem Server scheidet der URL-Import aus, der Weg über POST /api/recipes/create/html-or-json mit JSON-LD im Feld data funktionierte im Test ebenfalls (201).

curl -s -X POST http://127.0.0.1:9925/api/recipes \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"Marker Linsensuppe"}'
Rezeptübersicht in Mealie mit importierten und angelegten Rezeptkarten
Rezeptübersicht nach dem Anlegen und dem Import per URL.

Für die Kantine lohnt es sich, Kategorien und Schlagworte (zum Beispiel „vegetarisch“) von Anfang an einheitlich zu pflegen.

Verifizieren: curl -s http://127.0.0.1:9925/api/recipes -H "Authorization: Bearer $TOKEN" listet das Rezept mit Name und Slug marker-linsensuppe.

Schritt 5: Reverse Proxy und TLS

Mealie spricht auf Port 9000 nur HTTP. Veröffentlichen Sie den Dienst nie ohne TLS, denn Anmeldedaten und Token laufen sonst im Klartext. Mit Caddy genügt ein Block, Zertifikate holt Caddy selbst (siehe Caddy als Reverse Proxy mit automatischem HTTPS):

mealie.example.de {
    reverse_proxy 127.0.0.1:9925
}

Tragen Sie dieselbe Adresse als BASE_URL ein. Eine falsche BASE_URL verhinderte im Test die Anmeldung nicht (200), dient laut Dokumentation aber als Grundlage für Benachrichtigungen und den OIDC-Rückruf. Die Seiteneinstellungen in der Administration prüfen das und melden außerdem, ob der Zugriff über HTTPS oder localhost erfolgt. Die Testinstanz lief hinter einem TLS-terminierenden Proxy, der Punkt „Sichere Website“ war grün.

Mealie-Administration, Seite Seiteneinstellungen, mit Konfigurationsprüfung zu Version, sicherem Zugriff und Basis-URL
Seiteneinstellungen: Die Prüfung meldet sicheren Zugriff über HTTPS und eine geänderte Basis-URL.

Verifizieren: curl -I https://mealie.example.de liefert 200, und die Seiteneinstellungen zeigen „Der Zugriff auf die Webseite erfolgt über localhost oder https“.

Schritt 6: Sicherung erstellen

Es gibt zwei Wege, die sich ergänzen. Erstens die eingebaute Sicherung unter Administration, Sicherungen oder per POST /api/admin/backups (Antwort 201). Sie schreibt eine Zip-Datei wie mealie_v3.28.0_2026.10.05.00.38.42.zip nach data/backups, im Test 461 KB. Die Datei liegt damit im selben Ordner, den Sie ohnehin sichern, sie ersetzt aber keine Kopie auf einem anderen System.

Mealie-Administration, Seite Sicherungen, mit einer Backup-Datei und den Schaltflächen Herunterladen und Wiederherstellen
Sicherungen: Backup erstellen, hochladen, herunterladen oder wiederherstellen.

Zweitens ein Archiv des Datenordners bei gestopptem Container. Die Dokumentation nennt das für SQLite den besten Weg:

cd /opt/mealie
docker compose stop mealie
sudo tar czf /srv/backup/mealie-data-$(date +%F).tgz -C data .
docker compose start mealie

Das Archiv war im Test 918 KB groß. Kopieren Sie es auf ein zweites Speichermedium und prüfen Sie die Wiederherstellung regelmäßig. Das ließe sich per Cron nachts automatisieren, ein paar Minuten Stillstand sind bei einer Rezeptverwaltung meist verkraftbar.

Verifizieren: ls -l data/backups zeigt die Zip-Datei, tar tzf /srv/backup/mealie-data-*.tgz | head listet ./mealie.db.

Schritt 7: Wiederherstellung durchspielen

Ein Backup zählt erst, wenn der Restore geklappt hat. Der Test lief mit dem Rezept „Marker Linsensuppe“. Nach dem Backup wurde es gelöscht (GET danach 404).

Weg A, Mealie-Backup: In der Oberfläche „Wiederherstellen aus Sicherung“ wählen oder per API:

curl -s -X POST "http://127.0.0.1:9925/api/admin/backups/mealie_v3.28.0_2026.10.05.00.38.42.zip/restore" \
  -H "Authorization: Bearer $TOKEN"

Antwort Restore successful, das Marker-Rezept war wieder da (200). Die Dokumentation warnt: Der Restore löscht alle aktuellen Daten der Datenbank und lässt sich nicht rückgängig machen. Bei PostgreSQL braucht der Mealie-Benutzer dafür vorübergehend Superuser-Rechte. Meldet sich Mealie danach nicht an, starten Sie den Container neu.

Weg B, Archiv: Container herunterfahren, Datenordner komplett löschen, Archiv entpacken, Besitzer setzen, starten:

docker compose down
sudo rm -rf data && mkdir data
sudo tar xzf /srv/backup/mealie-data-2026-10-05.tgz -C data
sudo chown -R 1000:1000 data
docker compose up -d

Nach dem Totalverlust des Ordners war das Rezept samt Benutzerkonto wieder vorhanden, die Anmeldung mit dem geänderten Passwort lief (200). Ein Neustart mit docker compose down und up -d ließ die Daten ebenfalls unberührt.

Verifizieren: Marker-Rezept abrufen (200 statt 404) und Anmeldung mit dem aktuellen Passwort.

Schritt 8: Updates, Rollback und Mealie entfernen

Die Entwickler raten, eine feste Version zu setzen und neue Versionen bewusst nach dem Lesen der Release Notes einzuspielen. Ablauf: Backup (Schritt 6), Tag in compose.yaml ändern, docker compose pull, docker compose up -d. Rollback bedeutet alten Tag setzen und das Archiv aus Schritt 6 zurückspielen, denn Mealie migriert die Datenbank beim Start. Ein Mealie-Backup einer anderen Version wirft laut Dokumentation beim Restore einen Fehler.

Warnung: docker compose down entfernt nur Container. Der Ordner data mit allen Rezepten, Bildern und Benutzern bleibt, bis Sie ihn mit rm -rf data löschen. Das ist endgültig und ohne Backup nicht rückgängig zu machen.

Verifizieren: Nach dem Update zeigt curl -s http://127.0.0.1:9925/api/app/about die neue Version und die Rezepte sind vollständig.

Troubleshooting

FehlerbildUrsache und Lösung
failed to resolve reference "ghcr.io/mealie-recipes/mealie:3.28.0": not foundTag ohne v. Richtig ist v3.28.0.
Bind for 127.0.0.1:9925 failed: port is already allocatedPort belegt. Anderen Host-Port wählen. Nach dem Freimachen zeigte docker port mealie bei einem einfachen up -d nichts an, erst docker compose up -d --force-recreate setzte die Bindung.
PermissionError: [Errno 13] Permission denied: '/app/data/groups'Container wurde direkt als fremder Benutzer gestartet. PUID und PGID nutzen, kein user: setzen.
403 User Registration is DisabledGewolltes Verhalten bei ALLOW_SIGNUP: "false".
400 BAD_RECIPE_DATA beim URL-ImportSeite enthält keine lesbaren Rezeptdaten oder blockiert den Abruf. Rezept manuell anlegen.
401 Could not validate credentialsToken nach Passwortänderung ungültig. Neu anmelden.
Seiteneinstellungen melden eine unerwartete Basis-URLBASE_URL prüfen und anpassen, Container neu erstellen.

Häufige Fragen

SQLite oder PostgreSQL?

Für eine Familie, eine Kantine oder einen kleinen Betrieb genügt SQLite. PostgreSQL lohnt bei vielen gleichzeitigen Benutzern, bei Datenhaltung auf einem NAS oder für Funktionen wie unscharfe Suche, die laut Dokumentation nur dort aktiv sind. Zwischen beiden wechseln Sie über Backup und Restore.

Muss ich :latest vermeiden?

Das Tag latest existiert, die Entwickler empfehlen aber ausdrücklich eine feste Version, damit Updates bewusst passieren.

Reicht das Mealie-Backup allein?

Nein. Es liegt auf demselben Datenträger wie die Daten. Kopieren Sie Zip oder Archiv an einen zweiten Ort.

Wie viele Personen darf ich einladen?

Die Dokumentation nennt für SQLite 1 bis 20 Benutzer als passenden Bereich. Eigene Lastmessungen gibt es hier nicht.

Fazit

Mealie läuft mit einer kurzen Compose-Datei und einem Datenordner. Wichtig sind drei Handgriffe direkt nach dem Start: Standardkonto ändern, Registrierung geschlossen lassen, TLS davorsetzen. Die Sicherung ist unkompliziert, solange Sie sie wirklich auf ein zweites System kopieren und die Wiederherstellung einmal geübt haben.

Weiterführende Anleitungen und Quellen

Eckdaten

MerkmalWert
Imageghcr.io/mealie-recipes/mealie:v3.28.0
PortContainer 9000, Host im Beispiel 127.0.0.1:9925
Daten./data nach /app/data (Datenbank, Bilder, Backups)
Wichtige VariablenALLOW_SIGNUP, PUID, PGID, TZ, BASE_URL
Architekturenlinux/amd64, linux/arm64
LizenzAGPL-3.0
MealieRezeptverwaltungDocker ComposeSelfhostingBackupRestoreReverse Proxy