Grocy mit Docker Compose: Vorratsverwaltung selbst hosten
Grocy verwaltet Vorräte, Mindesthaltbarkeit und Einkaufszettel für Haushalt und kleines Büro. Diese Anleitung zeigt die Installation mit Docker Compose und dem Image von LinuxServer.io, die sichere Erstkonfiguration, die REST-API, Backup und Restore des Datenordners, das Update von 4.7.0 auf 4.7.1 und echte Fehlerbilder aus dem Test.
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

Grocy ist eine selbst gehostete Haushalts- und Vorratsverwaltung, die sich selbst als „ERP für den Kühlschrank“ beschreibt. Sie erfassen Produkte mit Lagerort, Menge und Mindesthaltbarkeit, buchen Einkäufe und Verbrauch und sehen auf einen Blick, was bald abläuft oder unter den Mindestbestand fällt. Dazu kommen Einkaufszettel, Rezepte und Speiseplan. Für kleine Büros eignet sich das ebenso, etwa für Kaffee, Getränke oder Druckerpatronen. Das Projekt steht unter MIT-Lizenz, ist in PHP geschrieben und speichert alles in einer SQLite-Datei. Diese Anleitung zeigt Installation, Erstkonfiguration auf Deutsch und Euro, den Betrieb mit der REST-API, Backup mit echtem Restore, das Update und die Fehlerbilder, die im Test tatsächlich aufgetreten sind. Grundlage ist ein Testlauf mit Grocy 4.7.0 und dem Update auf 4.7.1.
Voraussetzungen
Grocy ist sehr genügsam. Die Anmeldeseite antwortete im Test rund 25 Sekunden nach dem Start, der komplette Ordner config belegte mit zwei Produkten etwa 1 MB, die Datenbank grocy.db rund 600 KB.
- Linux-Server, Mini-PC oder NAS mit Docker Engine und Docker Compose v2, x86_64 oder ARM64 (das Image gibt es für
amd64undarm64v8) - 1 CPU-Kern und 1 GB RAM reichen für einen Haushalt oder ein kleines Büro; mit 2 Kernen und 2 GB haben Sie Reserve für weitere Dienste
- 5 GB freier Speicher für Daten, Produktbilder und lokale Backup-Archive
- ein freier Port (hier 9283) und für den Zugriff von außen ein Reverse Proxy mit HTTPS
- Grundkenntnisse in Docker Compose, siehe Docker Compose Grundlagen
Eckdaten
| Punkt | Wert |
|---|---|
| Image | lscr.io/linuxserver/grocy:4.7.1 (Grocy 4.7.1 vom 04.09.2026, Build v4.7.1-ls345) |
| Port | Host 9283 auf Container 80 |
| Volume | ./config:/config mit data/grocy.db und data/config.php |
| Umgebung | PUID, PGID, TZ, optional jede Einstellung mit Präfix GROCY_ |
| Standard-Login | admin / admin, sofort ändern |
| Datenbank | SQLite, im Test Schema-Version 257 |
| API | REST unter /api, Header GROCY-API-KEY |
Schritt 1: Projektordner und Compose-Datei anlegen
Die README von Grocy nennt für Docker ausschließlich das Image von LinuxServer.io. Es bündelt Nginx, PHP-FPM und Grocy in einem Container, legt die Konfiguration beim ersten Start an und verschiebt das Datenverzeichnis nach /config/data. Pinnen Sie die Version über eine Variable, dann ist ein Update später eine Zeile in der .env. Neben 4.7.1 gibt es Tags wie v4.7.1-ls345, die zusätzlich den Build von LinuxServer.io festschreiben.
mkdir -p /opt/grocy && cd /opt/grocy
Die Datei compose.yaml:
services:
grocy:
image: lscr.io/linuxserver/grocy:${GROCY_TAG:-4.7.1}
container_name: grocy
environment:
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
- TZ=${TZ:-Europe/Berlin}
- GROCY_CURRENCY=EUR
- GROCY_DEFAULT_LOCALE=de
volumes:
- ./config:/config
ports:
- "9283:80"
restart: unless-stopped
Die Datei .env:
GROCY_TAG=4.7.1
PUID=1000
PGID=1000
TZ=Europe/Berlin
Laut config-dist.php liest Grocy jede Einstellung auch aus einer Umgebungsvariable mit Präfix GROCY_. So bleiben Sprache und Währung in der Compose-Datei dokumentiert. PUID und PGID sollten zu dem Benutzer passen, dem /opt/grocy gehört (id -u, id -g).
Verifizieren: docker compose config gibt die aufgelöste Konfiguration ohne Fehler aus, das Image steht dort mit :4.7.1.
Schritt 2: Container starten und Migration auslösen
docker compose up -d
docker compose logs --no-log-prefix | grep -E "Linuxserver.io version|ls.io-init"
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" http://localhost:9283/
Im Log erscheint die Build-Version, zum Beispiel Linuxserver.io version: v4.7.1-ls345, und am Ende [ls.io-init] done.. Wichtig ist der erste Aufruf der Startseite: Grocy legt das Datenbankschema erst an, wenn jemand / öffnet. Im Test führte ein Login-Versuch direkt nach dem Start, ohne vorherigen Aufruf von /, zu HTTP 500 und im Nginx-Log zu no such table: migrations. Nach einem Aufruf der Startseite war alles in Ordnung. LinuxServer.io weist in der Image-Doku aus demselben Grund darauf hin, nach jedem Upgrade die Wurzel aufzurufen.
Verifizieren: Der curl-Aufruf liefert 302 http://localhost:9283/stockoverview bzw. ohne Anmeldung eine Weiterleitung, docker compose ps zeigt Up, und http://SERVER:9283/login zeigt das Anmeldeformular.
Schritt 3: Standardpasswort ändern und API-Schlüssel anlegen
Melden Sie sich mit admin und admin an und ändern Sie das Passwort sofort über das Benutzermenü oben rechts. Solange das Standardpasswort gilt, kann jeder im Netz Ihren Bestand lesen und ändern. Legen Sie für Skripte unter Einstellungen, API-Schlüssel verwalten einen Schlüssel an. Im Test hatte ein neuer Schlüssel das Ablaufdatum 2999-12-31, er gilt also praktisch unbegrenzt. Löschen Sie Schlüssel, die Sie nicht mehr brauchen.

Das Passwort lässt sich auch per API ändern, was sich für automatisierte Installationen anbietet. Der Benutzer admin hat die ID 1:
KEY='ihr-api-schluessel'
curl -s -w "%{http_code}\n" -X PUT http://localhost:9283/api/users/1 \
-H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{"username":"admin","first_name":"","last_name":"","password":"NEUES-PASSWORT"}'
Die Antwort war im Test 204. Ein anschließender Login mit admin/admin leitete auf /login?invalid=true um, der Login mit dem neuen Passwort auf die Startseite.
Verifizieren: curl -s -o /dev/null -w "%{http_code}\n" -H "GROCY-API-KEY: falsch" http://localhost:9283/api/system/info liefert 401, ohne Header ebenfalls 401, mit gültigem Schlüssel 200 und JSON mit "Version":"4.7.1".
Schritt 4: Sprache, Währung und Stammdaten
Mit GROCY_DEFAULT_LOCALE=de zeigte die Oberfläche im Test „Bestandsübersicht“ und Beträge als „1,29 €“. Bei der ersten Migration legt Grocy außerdem Beispiel-Stammdaten in der eingestellten Sprache an, im Test den Standort „Kühlschrank“ und die Mengeneinheiten „Stück“ und „Packung“. Beachten Sie die Reihenfolge der Spracheinstellungen: Ein Browser mit englischer Sprachpräferenz bekam trotz DEFAULT_LOCALE die englische Oberfläche. Erst die Benutzereinstellung locale setzte Deutsch auch für diesen Browser durch, entweder unter Benutzereinstellungen oder per API:
curl -s -X PUT http://localhost:9283/api/user/settings/locale \
-H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" -d '{"value":"de"}'
Stammdaten wie Lagerorte und Produkte legen Sie unter Stammdaten verwalten an oder per API über die generischen Objekt-Endpunkte:
curl -s -H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{"name":"Vorratsschrank Keller"}' http://localhost:9283/api/objects/locations
curl -s -H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{"name":"Haferflocken","location_id":3,"qu_id_purchase":3,"qu_id_stock":3,"min_stock_amount":2}' \
http://localhost:9283/api/objects/products
Die Antworten enthalten die neue ID, etwa {"created_object_id":"3"}. Die IDs der Mengeneinheiten lesen Sie vorher mit GET /api/objects/quantity_units aus.
Verifizieren: curl -s -H "GROCY-API-KEY: $KEY" http://localhost:9283/api/objects/locations listet den neuen Lagerort, und das Produkt erscheint unter Stammdaten verwalten, Produkte.
Schritt 5: Bestand buchen und verbrauchen
Einkäufe buchen Sie über Einkauf, Verbrauch über Verbrauch. Für Barcode-Scanner, Kurzbefehle oder Hausautomation ist die API praktischer:
curl -s -H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{"amount":3,"best_before_date":"2026-12-31","price":1.29,"transaction_type":"purchase"}' \
http://localhost:9283/api/stock/products/1/add
curl -s -H "GROCY-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{"amount":2,"transaction_type":"consume"}' \
http://localhost:9283/api/stock/products/1/consume
Grocy prüft Buchungen gegen den Bestand. Der Versuch, 50 Packungen bei einer vorhandenen Packung zu verbrauchen, endete im Test mit HTTP 400 und Amount to be consumed cannot be > current stock amount. Nach den Buchungen meldete /api/stock/volatile die Haferflocken als fehlend, weil eine Packung unter dem Mindestbestand von zwei liegt.

Verifizieren: curl -s -H "GROCY-API-KEY: $KEY" http://localhost:9283/api/stock zeigt das Produkt mit "amount":1, die Bestandsübersicht zeigt „1 Produkt ist unter Mindestbestand“, und das Bestandsjournal listet Einkauf und Verbrauch mit Benutzer und Zeitpunkt.

Schritt 6: Backup erstellen
Alle Daten liegen in ./config: die Datenbank data/grocy.db, die data/config.php, hochgeladene Bilder und die Plugins. Stoppen Sie den Container kurz, damit die SQLite-Datei in einem konsistenten Zustand gesichert wird:
cd /opt/grocy
docker compose stop grocy
mkdir -p backup
tar czf backup/grocy-config-$(date +%F).tar.gz config
docker compose start grocy
tar tzf backup/grocy-config-*.tar.gz | grep -E "grocy.db|config.php$"
Das Archiv war im Test 64.685 Byte groß. Das Image enthält kein sqlite3. Für eine Integritätsprüfung der gesicherten Datenbank nutzen Sie einen kurzlebigen Hilfscontainer:
docker run --rm -v /opt/grocy/config/data:/d:ro alpine sh -c \
'apk add -q sqlite >/dev/null && sqlite3 /d/grocy.db "PRAGMA integrity_check;"'
Kopieren Sie die Archive zusätzlich auf ein anderes System.
Verifizieren: tar tzf listet config/data/grocy.db und config/data/config.php, die Integritätsprüfung gibt ok aus.
Schritt 7: Restore durchführen
Ein Backup ist erst etwas wert, wenn der Restore funktioniert. Im Test wurde vor dem Backup ein Produkt „MARKER-Restore-1019“ angelegt, danach der Ordner config komplett gelöscht und aus dem Archiv zurückgeholt:
cd /opt/grocy
docker compose stop grocy
rm -rf config
tar xzf backup/grocy-config-2026-10-19.tar.gz
docker compose up -d --force-recreate
curl -s -o /dev/null http://localhost:9283/
Das --force-recreate ist kein Zierrat: Der Container merkt sich intern einen Verweis von /app/www/data auf /config/data. Wird nur neu gestartet, während config leer ist, scheitert die Initialisierung (siehe Troubleshooting). Nach dem Restore waren beide Produkte mit ihren Mengen wieder da. Der Login mit admin/admin wurde abgewiesen, das geänderte Passwort galt weiter, und der alte API-Schlüssel funktionierte, weil Benutzer und Schlüssel in grocy.db liegen.
Verifizieren: curl -s -H "GROCY-API-KEY: $KEY" http://localhost:9283/api/stock listet das Marker-Produkt, und die Anmeldung gelingt mit dem zuletzt gesetzten Passwort.
Schritt 8: Update auf eine neue Version
Das update.sh aus der README gilt für klassische Installationen und ist im Container nicht vorhanden. Beim Docker-Betrieb wechseln Sie den Image-Tag. Im Test lief die Instanz zunächst mit GROCY_TAG=4.7.0 und wurde dann angehoben:
cd /opt/grocy
docker compose stop grocy
tar czf backup/grocy-vor-update-$(date +%F).tar.gz config
sed -i 's/^GROCY_TAG=.*/GROCY_TAG=4.7.1/' .env
docker compose pull
docker compose up -d
curl -s -o /dev/null http://localhost:9283/
curl -s -H "GROCY-API-KEY: $KEY" http://localhost:9283/api/system/info
Vorher meldete /api/system/info Version 4.7.0, danach 4.7.1 mit Release-Datum 2026-09-04, PHP 8.5.6 und SQLite 3.53.4. Die Schema-Version blieb bei 257, das Marker-Produkt war unverändert vorhanden. Prüfen Sie vor größeren Sprüngen die Release-Hinweise und config-dist.php auf neue Optionen.
Verifizieren: docker compose ps zeigt das Image mit :4.7.1, das Log Linuxserver.io version: v4.7.1-ls345, und /api/system/info liefert "Version":"4.7.1".
Troubleshooting
| Symptom | Ursache | Lösung |
|---|---|---|
Login oder API liefert HTTP 500, im Log no such table: migrations | Startseite nach Erststart oder Update noch nicht aufgerufen | / einmal öffnen, danach erneut anmelden |
Seite zeigt Unable to run Grocy: config.php in data directory ... not found, Container steht auf Up | config gelöscht oder geleert und Container nur neu gestartet | Backup zurückspielen und docker compose up -d --force-recreate |
Oberfläche englisch trotz GROCY_DEFAULT_LOCALE=de | Browsersprache hat Vorrang vor der Standardsprache | Benutzereinstellung locale auf de setzen |
API antwortet 401 | Schlüssel fehlt, ist falsch oder wurde gelöscht | Header GROCY-API-KEY prüfen, Schlüssel neu anlegen |
Buchung liefert 400 mit Amount to be consumed cannot be > current stock amount | Mehr verbraucht als gebucht | Bestand per Inventur korrigieren |
Der zweite Fall ist tückisch. Im Test enthielt das Log cp: cannot create regular file '/config/data/config.php': No such file or directory, die Initialisierung endete trotzdem mit [ls.io-init] done., und die Seite antwortete mit HTTP 200 samt Fehlermeldung. Images von LinuxServer.io bleiben bei solchen Fehlern im Status Up. Beurteilen Sie den Start deshalb immer anhand von Log und Seiteninhalt, nie allein nach docker compose ps:
docker compose logs --no-log-prefix | grep -iE "cannot|error|fatal"
tail -n 20 config/log/nginx/error.log
Häufige Fragen
Warum kein offizielles Image des Grocy-Projekts?
Der Entwickler pflegt kein eigenes Container-Image, die README verweist für Docker direkt auf LinuxServer.io. Die Build-Nummer im Tag (-ls345) zählt bei jedem Neubau hoch.
Kann ich Grocy direkt ins Internet stellen?
Besser nicht ohne Reverse Proxy mit HTTPS. Das Image bringt nur ein selbstsigniertes Zertifikat mit. Setzen Sie einen Proxy wie Traefik mit HTTPS davor oder erreichen Sie Grocy nur über VPN. Für den Port reicht dann 127.0.0.1:9283:80.
Wie bekomme ich Euro und Deutsch für alle Benutzer?
Mit GROCY_CURRENCY=EUR und GROCY_DEFAULT_LOCALE=de in der Compose-Datei. Bei Benutzern mit englischsprachigem Browser setzen Sie zusätzlich die Benutzereinstellung Sprache.
Reicht es, nur die Datei grocy.db zu sichern?
Für die Inhalte ja, aber Produktbilder, eigene Plugins und die config.php liegen daneben. Sichern Sie den ganzen Ordner config, er ist klein.
Fazit
Grocy ist mit einem Container, einem Ordner und einer SQLite-Datei schnell aufgesetzt und leicht zu sichern. Die zwei Stolperstellen sind die Migration, die erst beim Aufruf der Startseite läuft, und die Neigung des Images, trotz gescheiterter Initialisierung als Up zu erscheinen. Wer das Standardpasswort sofort ändert, Sprache und Währung per Umgebungsvariable festlegt, den Tag pinnt und den Restore einmal geübt hat, bekommt eine robuste Vorratsverwaltung für Haushalt und kleines Büro.
Weiterführende Anleitungen und Quellen
- Homebox mit Docker Compose: Inventarverwaltung für IT-Assets
- Mealie mit Docker Compose: Rezeptverwaltung mit Backup
- Tandoor Recipes mit Docker Compose selbst hosten
- Grocy auf GitHub (README, Installation, Update)
- Grocy Release v4.7.1
- Grocy config-dist.php (Einstellungen, GROCY_-Variablen)
- linuxserver/grocy auf Docker Hub
- linuxserver/docker-grocy auf GitHub
- Projektseite grocy.info


