Matthias S. schrieb:
> ich habe mir einen Rechner mit div. Docker-Containern zerschossen. Dabei
> durfte ich feststellen, dass meine BackUp-Strategrie wohl nicht die
> beste war. Die beruhte drauf mit Resiliosync das
> Docker-Volume-Verzeichnis /var/lib/docker/volumes auf einen anderen
> Rechner zu synchronisieren.
"Nicht die beste BackUp-Strategrie" ist eine feine Untertreibung. :-)
> Einige Container konnte ich ganz gut wieder zu laufen bringen, in dem
> ich nach dem zurück kopieren (mithilfe eines Docker-Containers) ein
> 'chmod -R 777 ./' über das Volume ausgeführt habe.
Auch ein "chmod -R 777" ist keine besonders gute Strategrie, aber das
haben die Kollegen in diesem Thread Dir ja bereits gesagt... So etwas
wie
1 | find <dir> -type d -print0 | xargs -0 -- chmod 755
|
2 | find <dir> -type f -print0 | xargs -0 -- chmod 644
|
ist immer meistens noch keine gute Strategrie, aber immerhin besser, als
alles (!) mit Lese-, Schreib- und Ausführrechten (!) zu versehen.
> Etwas kurios ist dagegen InfluxDB (1.8):
> Daten des Volumes zurück kopiert, 'chmod -R 777 ./' darüber ausgeführt.
Und kein chown(1)? Hm.
> Container läuft, Datenbanken sind da, Benutzer sind da, NodeRed kann
> Daten reinschreiben, Grafana kann Daten auslesen. Aber: alle bisherigen
> Daten sind irgendwie weg, bzw. Grafana zeigt diese nicht mehr an -
> obwohl die ja eigentlich da drinnen stecken sollten?
Leider kenne ich mich mit InfluxDB nicht aus, dafür aber mit einigen
anderen Datenmanagementsystemen. Manche davon haben SEHR eigenwillige
Vorstellungen davon, wem ihre Dateien und Verzeichnisse zu gehören und
welche Permissions sie gefälligst zu haben haben. Das hier (vom klugen
Ernst, natürlich) schon genannte PostgreSQL etwa verweigert den Start,
wenn sein Datenverzeichnis nicht dem Benutzer "postgres" gehört, oder
nicht die Permissions 0700 oder 0750 hat. Das ist auch gut so, denn in
den Daten eines Datenmanagementsystems hat außer ihm selbst natürlich
grundsätzlich nichts etwas zu suchen.
Und dann, hach ja, die Benutzerkennungen oder, genauer, die User-IDs.
Weil so ein Linux-Setup ein, sagen wir mal... schwer vorhersagbares Ding
ist, werden Benutzerkennungen häufig dynamisch vergeben, auch für
Daemon- und Systemuser. Mit on-the-fly gestarteten Docker-Containern
läßt sich das leicht überprüfen: installiere ich dort zuerst InfluxDB
und dann PostgreSQL, dann sehen die UID so aus:
1 | username | uid
|
2 | ---------+-----
|
3 | influxdb | 100
|
4 | postgres | 102
|
Installiere ich hingegen zuerst PostgreSQL und dann InfluxDB, haben die
User plötzlich ganz andere User-IDs:
1 | username | uid
|
2 | ---------+-----
|
3 | postgres | 101
|
4 | influxdb | 102
|
(Vor PostgreSQL wird noch ein User "messagebus" angelegt, aber das
spielt hier keine Rolle.)
Du siehst: die Benutzerkennungen, unter denen Deine Prozesse innerhalb
Deiner Container laufen, sind nicht immer dieselben -- und, Achtung:
auch nicht die auf Deinem Hostsystem. Das führt hier bei mir
beispielsweise zu der lustigen Situation, daß die Datendateien meines
OpenSearch-Containers im Container die User-ID 1000 des Benutzers
"opensearch", aber auf dem Host die User-Id meines normalen
Shellbenutzers haben. In meinem Redis-Container hat der Redis-Server die
Benutzerkennung "redis" mit der User-ID 999, die auf meinem Host dem
User "systemd-coredump" vorbehalten ist.
Also -- und das ist der Punkt -- in Deinen Docker-Volume-Verzeichnissen
auf Deinem Host, also: jenen Verzeichnissen, die Du mit Deiner
"Backup-Strategrie" herum kopierst, legen die Prozesse Deiner Containern
ihre Daten unter jener User-ID ab, mit der die Prozesse in Deinen
Containern laufen. Die muß nicht einmal mit Deinem Host konsistent sein,
und ist es höchstwahrscheinlich auch nicht zwischen verschiedenen
Docker-Containern (oder -Generationen).
Okay, wie gehen wir mit dem "Problem" jetzt um? Da gibt es verschiedene
Ideen und Strategien, die erste ist ein Feature namens userns-remaß,
also Sub-UIDs und Sub-GIDs, die Manpages dazu gibt es in subuid(5) und
subgid(5). Damit lassen sich Unter-IDs für Systembenutzer einrichten,
aber Achtung: Docker läuft entweder mit oder ohne, und wer dieses
Feature einschaltet, muß wissen, daß seine existierenden Container dann
nicht mehr starten. Siehe auch [1].
Dann gibt es die Möglichkeit, feste User-IDs in den Containern bereits
beim Erzeugen der Images festzulegen, sei es mit useradd(8) oder
adduser(8), oder (diese Möglichkeit ist eher unbekannt) indem einfach
die passenden Dateien passwd und group in /etc des Image angelegt
werden, bevor die gewünschte Software installiert wird. Einfach ein
1 | echo 'nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin' > /etc/passwd
|
2 | echo 'nogroup:x:65534:' > /etc/group
|
im "RUN" eines Dockerfile und danach ein "USER nobody", schon läuft der
ganze Prozess im Container als "nobody" mit der User-ID 65534. Ebenso
kann man eine definierte User-ID beispielsweise für Benutzer wie
"postgres" oder "influxdb" anlegen, bevor die betreffende Software im
Image installiert wird -- oder wenn sie bereits installiert ist, mit
usermod(8) die angelegten User modifizieren und ihnen fest vorgegebene
User-IDs zuzuweisen (dann allerdings auch die bei der Installation
angelegten Dateien und Verzeichnisse... genau). Die letztere Möglichkeit
funktioniert sogar, ohne daß die Benutzerverwaltungswerkzeuge im Image
installiert worden sind.
Wie dem auch sei: am Ende wirst Du für jede halbwegs zuverlässige
Strategie reproduzierbare User- und Group-IDs brauchen.
[1] https://docs.docker.com/engine/security/userns-remap/
> Bessere Idee für BackUps? Interessant wäre ja:
> https://github.com/alaub81/backup_docker_scripts
> Da ich über das BackUp dann auch noch ein versioniertes BackUp laufen
> lasse (Duplicati), würde ich mir in dieses jede Menge große Volumes
> reinspeichern, was auch irgendwie doof ist...
Was nützt Dir die beste Backup-Strategrie, wenn Du das Restore nicht
getestet hast? Richtig: nichts, oder, anders gesagt: hast Du kein
Backup. Und ohne Dir zu Nahe treten zu wollen: einfach nur Daten
irgendwohin sichern kostet zwar Speicherplatz, bietet Dir aber keine
Garantie, sie im Falle eines Desasters wiederherstellen zu können. Und
Dir irgendwas un- oder halb Verstandenes aus dem Internet zusammen zu
kopieren, macht die Sache kaum besser.
In meinem ganz persönlichen Fall sind die allermeisten Images selbst
erzeugt, und haben ein eigenes Programm als ENTRYPOINT. Je nachdem, wie
es aufgerufen wird, arbeitet es als reiner Entrypoint und nutzt den
Systembefehl exece(2), um den "eigentlichen" Entrypoint des Image zu
starten. Gleichzeitig fungiert es mit den passenden Argumenten aber
auch als HEALTHCHECK und bei Containern, die Daten persistieren, werden
diese in Tarballs auf STDOUT gedumpt oder aus ebensolchen von STDIN
restauriert. Dadurch haben die Images eine einheitliche Bedienung, die
sich obendrein über Labels prima automatisieren läßt. Das ist zwar ein
bisschen Arbeit, aber sehr komfortabel. Und es verträgt sich prima mit
meinen versionierten Backups (noch rsnapshot, künftig wohl Borg).
Wie dem auch sei: wenn Deine Datenmengen nicht exorbitant groß oder
variant sind, dann ist es meist einfacher, Deine Daten mit "docker exec"
erstmal in einen konsistenten Dump zu überführen und dann ins Backup zu
schieben. Die meisten mir bekannten Backupwerkzeuge bieten die Option,
vor dem Anfertigen eines neuen Backup ein oder mehrere Skripte
auszuführen. Nutze sie.