Nextcloud mit Docker: Setup, Vor- und Nachteile – und vier Stolperfallen aus der Praxis
Wer seine Dateien, Kalender und Fotos nicht dauerhaft bei einem Cloud-Konzern liegen lassen will, landet früher oder später bei Nextcloud: die eigene Cloud auf dem eigenen Server, erreichbar von überall. Richtig angenehm wird die Sache, wenn Nextcloud in Docker läuft – in einer halben Stunde aufgesetzt, sauber gekapselt und leicht zu warten.
Wo Licht ist, ist aber bekanntlich auch Schatten. Ich zeige dir hier das Setup, die ehrlichen Vor- und Nachteile einer Docker-Installation und vier Probleme, über die ich im Admin-Alltag tatsächlich gestolpert bin – jeweils mit der Lösung und den Befehlen zum Kopieren.
1. Das Setup: Nextcloud mit Docker Compose
Docker Compose beschreibt den kompletten Aufbau in einer Datei, die zugleich die Dokumentation ist. Der Aufbau hier ist bewusst schlicht: Nextcloud (nextcloud:apache) mit MariaDB als Datenbank.
Lege auf dem Server ein Verzeichnis an und erstelle darin die Datei .env für die Passwörter. Die Passwörter gehören nicht in die Compose-Datei selbst – sie solltest du später sorglos teilen oder in ein Repository legen können:
# .env – Zugriffsrechte: chmod 600 .env
MYSQL_ROOT_PASSWORD=hier_ein_langes_root_passwort
MYSQL_PASSWORD=hier_ein_anderes_langes_db_passwort
Danach die compose.yaml:
services:
db:
image: mariadb:11
container_name: nextcloud_db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
app:
image: nextcloud:apache
container_name: nextcloud_app
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
volumes:
- nextcloud:/var/www/html
- ./data:/var/www/html/data
environment:
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_HOST: db
NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
PHP_MEMORY_LIMIT: 512M
volumes:
db:
nextcloud:
Das Datenverzeichnis der Nutzer liegt hier bewusst außerhalb des Containers als ./data. So sicherst du später nur die Nutzerdaten, die Datenbank und die Konfiguration – und nicht das ganze Programmverzeichnis. Das Verzeichnis muss dem Benutzer www-data gehören, also UID 33:
mkdir -p data
sudo chown 33:33 data
docker compose up -d
Danach ist die Nextcloud unter http://SERVER-IP:8080 erreichbar, und du legst im Browser den Administrator-Account an. Zwei Hinweise dazu: NEXTCLOUD_TRUSTED_DOMAINS wird nur bei der ersten Einrichtung ausgewertet (später per occ nachziehen, siehe Abschnitt 4), und der Zugriff über http ist nur für den ersten Test gedacht – nach außen gehört das hinter HTTPS.
2. Vor- und Nachteile einer Docker-Installation
Was dafür spricht
- Isolation und Sauberkeit: Die PHP-Version und alle Erweiterungen kommen aus dem Image. Nichts davon fasst das Host-System an, und ein Versionssprung zerschießt keine Systempakete.
- Portabilität: Compose-Datei plus Volumes auf einen anderen Server umziehen ist eine Sache von Minuten.
- Nachvollziehbares Update: Neues Image ziehen, Datenbank migrieren lassen, fertig.
- Die Konfiguration ist dokumentiert: Wer die
compose.yamlliest, weiß, wie die Installation aussieht. Bei klassisch installierten Systemen ist das oft Rätselraten.
Was dagegen spricht
- Storage-I/O: Alles läuft über das Overlay-Dateisystem des Containers. Bei langsamen Datenträgern und erst recht bei Netzlaufwerken wird das zum Flaschenhals.
- Fehlersuche braucht Docker-Wissen: Du kommst nicht mehr mit
nano /etc/php/...an die Systemdateien, sondern musst überocc,docker execunddocker logsarbeiten. - Updates sind Handarbeit: Nextcloud aktualisiert sich hier nicht von allein. Wer das
upgradevergisst, hängt irgendwann auf einer alten und dann unsicheren Version fest. - Backups gehören dazu: Volumes enthalten Daten und Datenbank. Eine laufende MariaDB-Datenbank darf man nicht einfach kopieren – sie braucht einen Dump (siehe Abschnitt 4).
3. Aus dem Praxis-Logbuch: vier Probleme und ihre Lösung
Wer produktiv mit Docker arbeitet, stolpert früher oder später über dieselben Hürden. Hier sind vier echte Fälle aus meinem Alltag.
Problem A: HTTP 500 nach dem Einrichten einer App (z. B. OneDrive-Anbindung)
Eine inkompatible App oder ein fehlerhaftes Update kann das komplette Nextcloud-Frontend lahmlegen – statt der Oberfläche kommt nur noch ein HTTP 500. Das Webinterface fällt damit als Werkzeug weg, also arbeiten wir in der Konsole im Container:
# Was ist überhaupt los? (die letzten Zeilen des Nextcloud-Logs)
docker exec -it nextcloud_app tail -n 50 /var/www/html/data/nextcloud.log
# Alle Apps auflisten
docker exec -it --user www-data nextcloud_app php occ app:list
# Verdächtige App abschalten (Daten bleiben erhalten)
docker exec -it --user www-data nextcloud_app php occ app:disable <app-id>
Achte darauf, erst zu deaktivieren und nicht sofort zu entfernen: app:disable lässt die Daten der App in Ruhe, app:remove löscht sie. Erst wenn klar ist, dass die App nicht mehr gebraucht wird, darf sie weg sein. Danach lohnt ein Reparaturlauf, der hängende Einträge aufräumt:
docker exec -it --user www-data nextcloud_app php occ maintenance:repair
Problem B: Nach dem Neuerstellen der Container ist das Netzwerk weg
Nach einem docker compose up -d --force-recreate erreichen sich die Container nicht mehr – oder der vorgeschaltete Reverse-Proxy findet die Nextcloud nicht mehr.
Der häufigste Grund: Der Proxy läuft in einem eigenen Compose-Projekt und damit in einem eigenen Docker-Netz. Wird die Nextcloud neu erstellt, hängt sie anschließend in einem anderen Netz, und die Verbindung zum Proxy ist weg. In diesem Fall gehört das gemeinsame Netz ausdrücklich in die Compose-Datei:
services:
app:
# ...
networks:
- default
- proxy
networks:
proxy:
external: true # existiert schon, z. B. vom Reverse-Proxy
Geordnet neu starten lässt sich der Stack so:
docker compose down
docker compose up -d
# Kontrolle: Ist der Container im richtigen Netz?
docker network inspect proxy
Warnung:docker network pruneist an dieser Stelle kein guter Rat. Der Befehl räumt alle nicht benutzten Netze weg – auf einem Server mit mehreren Stacks reißt das anderen Anwendungen die Verbindung ab. Wenn überhaupt, dann gezielt:docker network rm <netz-id>.
Problem C: Docker-Datenverzeichnis auf ein Netzlaufwerk verlegen
Wenn die Platte knapp wird, liegt der Gedanke nahe, /var/lib/docker auf ein NAS oder ein gemountetes Netzlaufwerk zu verschieben. Danach starten Container nicht mehr oder verhalten sich seltsam – denn das Standard-Dateisystem für Container-Schichten, overlay2, funktioniert auf NFS nicht zuverlässig:
# Symptom im Log des Docker-Dienstes
sudo journalctl -u docker -n 50
# Aktuell aktiver Storage-Treiber
docker info | grep -i "storage driver"
Der oft zitierte Ausweg, den Treiber auf vfs umzustellen, ist ein Notnagel und kein Ziel: vfs kopiert jede Container-Schicht vollständig, der Platzbedarf explodiert und alles wird deutlich langsamer.
Der bessere Weg ist eine Aufteilung: Docker selbst bleibt mit seinem Datenverzeichnis auf einer lokalen Platte, und nur die Nutzerdaten der Nextcloud liegen auf dem Netzlaufwerk. Genau dafür ist der Bind-Mount ./data aus Abschnitt 1 da. Läuft das Verzeichnis über NFS, gehört außerdem ein File-Locking über Redis dazu, sonst kann Nextcloud gleichzeitige Zugriffe nicht sauber auflösen (siehe Abschnitt 4).
Problem D: Nach einem unerwarteten Reboot läuft nichts wieder an
Stromausfall, Kernel-Panic, harter Neustart: Danach war die Weboberfläche einfach weg – weil der Container nicht automatisch gestartet ist. restart: unless-stopped in der Compose-Datei (siehe oben) sorgt dafür, dass Docker den Container nach einem Neustart von sich aus wieder hochzieht. Zusätzlich muss der Docker-Dienst selbst beim Booten starten:
sudo systemctl enable --now docker
# Nach einem Neustart kontrollieren:
docker ps
docker compose ps
4. Was ich produktiv zusätzlich einrichte
Für einen Test reicht das Setup aus Abschnitt 1. Sobald die Nextcloud aber echte Daten bekommt, kommen fünf Dinge dazu:
HTTPS über einen Reverse-Proxy
Nextcloud gehört nicht unverschlüsselt ins Netz. Bei mir läuft davor ein nginx-proxy-manager, der die TLS-Zertifikate automatisch holt und die Anfragen an Port 8080 weiterreicht. Damit Nextcloud die Aufrufe richtig bewertet, muss sie über den Proxy Bescheid wissen:
docker exec -it --user www-data nextcloud_app php occ config:system:set trusted_domains 1 --value=cloud.example.com
docker exec -it --user www-data nextcloud_app php occ config:system:set overwrite.cli.url --value=https://cloud.example.com
docker exec -it --user www-data nextcloud_app php occ config:system:set overwriteprotocol --value=https
docker exec -it --user www-data nextcloud_app php occ config:system:set trusted_proxies 0 --value=172.18.0.1
Die IP bei trusted_proxies ist die Adresse des Proxy-Containers im Docker-Netz – die ermittelst du mit docker network inspect. Ohne diesen Eintrag zeigt Nextcloud falsche Links, und Nutzer werden auf http umgeleitet.
Redis für Sperren und Cache
Redis übernimmt das Datei-Locking (wichtig bei Netzlaufwerken) und den Zwischenspeicher. Als zusätzlicher Dienst in der Compose-Datei:
redis:
image: redis:alpine
container_name: nextcloud_redis
restart: unless-stopped
Anschließend in den Container-Einstellungen REDIS_HOST: redis ergänzen und Nextcloud umkonfigurieren:
docker exec -it --user www-data nextcloud_app php occ config:system:set memcache.distributed --value="\OC\Memcache\Redis"
docker exec -it --user www-data nextcloud_app php occ config:system:set memcache.locking --value="\OC\Memcache\Redis"
docker exec -it --user www-data nextcloud_app php occ config:system:set redis host --value=redis
docker exec -it --user www-data nextcloud_app php occ config:system:set redis port --value=6379 --type=integer
Hintergrundaufgaben über Cron
Standardmäßig erledigt Nextcloud Hintergrundjobs im Vorbeigehen, wenn jemand die Seite aufruft. Sauberer ist der Cron-Modus: In den Verwaltungseinstellungen auf Cron umstellen oder per occ background:cron – dazu ein Cronjob auf dem Server, der die Aufgabe minütlich anstößt.
Ein Backup, das diesen Namen verdient
Drei Dinge gehören gesichert: die Nutzerdaten, die Datenbank und die Konfiguration. Bei der Datenbank ist der Dump Pflicht, ein Kopieren der laufenden MariaDB-Dateien ergibt keinen konsistenten Stand:
# Datenbank sichern
docker exec nextcloud_db sh -c 'exec mariadb-dump --single-transaction \
--default-character-set=utf8mb4 -u root -p"$MYSQL_ROOT_PASSWORD" nextcloud' \
> nextcloud-db-$(date +%F).sql
# Programm- und Datenvolume sichern
docker run --rm -v nextcloud_nextcloud:/data -v "$PWD":/backup alpine \
tar czf /backup/nextcloud-app-$(date +%F).tar.gz -C /data .
Die Volume-Namen bekommst du mit docker volume ls – sie setzen sich aus Projekt- und Volumenname zusammen. Wichtig: Vor dem Sichern der Volumes in den Wartungsmodus gehen und danach wieder heraus, sonst schreibt jemand mitten in die Sicherung hinein:
docker exec -it --user www-data nextcloud_app php occ maintenance:mode --on
# ... Sicherung ...
docker exec -it --user www-data nextcloud_app php occ maintenance:mode --off
Updates
Der Update-Weg in Kurzform – und ja, der Wartungsmodus gehört dazu:
docker exec -it --user www-data nextcloud_app php occ maintenance:mode --on
docker compose pull
docker compose up -d
docker exec -it --user www-data nextcloud_app php occ upgrade
docker exec -it --user www-data nextcloud_app php occ maintenance:mode --off
Fazit
Nextcloud in Docker ist ein starkes Paket – wenn man weiß, wie man im Ernstfall eingreift. Die Fallen liegen selten in Nextcloud selbst, sondern drumherum: Netzwerke, Storage, Neustarts, Backups. Mit ein paar occ-Befehlen, einer ehrlichen compose.yaml und einem Backup, das tatsächlich läuft, sind Ausfälle schnell abgefangen. Und wer das nicht selbst betreiben will: Genau das ist die Arbeit, die ich hier täglich mache.
Computerservice Bullmann hilft vor Ort in Dénia und per Fernwartung. Telefon, Telegram und Fernwartung findest du auf der Startseite.