v0.8.02-beta - doctor ziet koppelingen onder BASE_DIR
Some checks failed
Deploy server-up (dev) / deploy (push) Has been cancelled

De koppeling van BASE_DIR kan intact zijn terwijl de container er toch niets
ziet. Docker bindt met propagation rprivate: een koppeling die op de host na
het aanmaken van de container ontstaat komt daar niet doorheen, en dan ziet de
container de lege map eronder.

- --doctor loopt met findmnt alle koppelingen onder BASE_DIR langs en
  vergelijkt met de mountlijst van de container
- ontbreekt er een, dan staat erbij welke en hoe je hem meekoppelt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
This commit is contained in:
Ramon 2026-08-03 21:59:49 +02:00
parent 34d0116efd
commit e0d387c499
4 changed files with 65 additions and 1 deletions

View file

@ -1,3 +1,26 @@
# v0.8.02-beta — Koppelingen ónder BASE_DIR
`--doctor` zei dat `/opt/serverup` netjes gekoppeld was, en dat klopte ook.
Alleen zag Server Up er geen enkele app, terwijl er op de host drie stonden.
De verklaring zit een niveau dieper. Docker bindt met propagation `rprivate`:
een koppeling die op de host **ná** het aanmaken van de container ontstaat, komt
daar niet doorheen. Is `stacks` (of `appdata`, of `backups`) een eigen mount —
een aparte dataset, een tweede schijf, een netwerkmap — dan ziet de container de
lege map eronder. De koppeling van `BASE_DIR` zelf is intact, dus daar valt
niets aan op te merken; het scherm blijft alleen leeg.
`--doctor` loopt nu met `findmnt` alle koppelingen onder `BASE_DIR` langs en
vergelijkt ze met wat de container in zijn eigen mountlijst heeft. Ontbreekt er
een, dan zegt hij welke, en hoe je hem meekoppelt:
```
✖ /opt/serverup/stacks is op de host een eigen koppeling, maar niet in de container
De container ziet daar de lege map eronder. Koppel hem apart mee in
docker-compose.yml:
- /opt/serverup/stacks:/opt/serverup/stacks
```
# v0.8.01-beta — "Nog 106 tonen" onder een leeg scherm
De app store toonde geen enkele kaart, met daaronder een knop die beloofde dat

View file

@ -1 +1 @@
0.8.01-beta
0.8.02-beta

View file

@ -1200,6 +1200,32 @@ PYEOF
fi
fi
fi
# Eigen koppelingen ónder BASE_DIR. Docker bindt met propagation
# "rprivate": een koppeling die op de host ná het aanmaken van de
# container ontstaat, komt daar niet doorheen. De container ziet dan de
# lege map eronder, terwijl op de host alles keurig gevuld is — en de
# koppeling van BASE_DIR zelf is intact, dus daar is niets aan te zien.
if heeft findmnt; then
_diep=0
for _mp in $(findmnt -rno TARGET -R "$_basis" 2>/dev/null); do
[ "$_mp" = "$_basis" ] && continue
_diep=1
if $SUDO docker exec server-up sh -c \
"grep -q ' $_mp ' /proc/self/mountinfo" 2>/dev/null; then
dok_ok "$_mp is een eigen koppeling en komt mee"
else
dok_fout "$_mp is op de host een eigen koppeling, maar niet in de container"
log " De container ziet daar de lege map eronder. Koppel hem"
log " apart mee in docker-compose.yml:"
log " - $_mp:$_mp"
log " of zorg dat de koppeling bestaat vóór de container start."
fi
done
[ "$_diep" -eq 0 ] && log "Geen eigen koppelingen onder $_basis"
else
dok_waar "findmnt ontbreekt; kon niet nagaan of er koppelingen onder $_basis liggen"
fi
# De app store leest uit de git-cache; is die leeg, dan is de lijst leeg.
_apps="$($SUDO docker exec server-up sh -c \
'find /data/git -name template.json 2>/dev/null | wc -l' \

View file

@ -1198,3 +1198,18 @@ def test_doctor_onderscheidt_ontbrekend_van_leeg():
assert "test -d" in blok, "er wordt niet gekeken of de map er is"
assert "bestaat niet binnen de container" in blok
assert "nog geen enkele app" in blok
def test_doctor_kijkt_naar_koppelingen_onder_base_dir():
"""Docker bindt met propagation "rprivate". Een koppeling die op de host ná
het aanmaken van de container ontstaat, komt daar niet doorheen: de
container ziet de lege map eronder, terwijl de koppeling van BASE_DIR zelf
intact is en er dus niets aan te zien is."""
tekst = SCRIPT.read_text(encoding="utf-8")
blok = tekst[tekst.index("Wat Server Up zelf ziet"):]
blok = blok[:blok.index("\n printf ")]
assert "findmnt" in blok, "er wordt niet naar koppelingen gekeken"
assert "/proc/self/mountinfo" in blok, "de containerkant wordt niet vergeleken"
assert "eigen koppeling, maar niet in de container" in blok
# De uitweg hoort erbij te staan, anders weet je nog niets.
assert "docker-compose.yml" in blok