docs: corrige receta de tmux-host (symlink /DATA/AppData + git ownership)
El comando docker run documentado no funcionaba realmente desde dentro del contenedor: /DATA/AppData es un symlink absoluto a /media/HDD-Storage/AppData, que queda roto si solo se monta /DATA. Agrega el mount que falta, el git safe.directory necesario (baked en el arranque, no persiste en el volumen de credenciales), y documenta ambos gotchas con como se detectaron.
This commit is contained in:
1 parent
a31a0d96b6
commit
61c57fbf28
1 file changed
+69
-1
@@ -54,18 +54,79 @@ docker run -d \
|
|||||||
--name tmux-host \
|
--name tmux-host \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
-v /DATA:/DATA \
|
-v /DATA:/DATA \
|
||||||
|
-v /media/HDD-Storage:/media/HDD-Storage \
|
||||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
-v /DATA/AppData/k3d-lab-v3/claude-code-home:/root/.claude \
|
-v /DATA/AppData/k3d-lab-v3/claude-code-home:/root/.claude \
|
||||||
--network host \
|
--network host \
|
||||||
alpine sh -c "apk add --no-cache tmux docker-cli bash curl git kubectl nodejs npm && npm install -g @anthropic-ai/claude-code && tail -f /dev/null"
|
alpine sh -c "apk add --no-cache tmux docker-cli bash curl git kubectl nodejs npm && npm install -g @anthropic-ai/claude-code && git config --global --add safe.directory '*' && tail -f /dev/null"
|
||||||
```
|
```
|
||||||
|
|
||||||
| Volumen | Destino | Por qué |
|
| Volumen | Destino | Por qué |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `/DATA` | `/DATA` | Acceso a los repos (`apps-registry`, `platform-infra`, `scripts`) y configs del lab, mismos paths que en el host |
|
| `/DATA` | `/DATA` | Acceso a los repos (`apps-registry`, `platform-infra`, `scripts`) y configs del lab, mismos paths que en el host |
|
||||||
|
| `/media/HDD-Storage` | `/media/HDD-Storage` | Ver "Gotcha: el symlink `/DATA/AppData`" abajo — sin esto, los repos no se ven dentro del contenedor pese a montar `/DATA` |
|
||||||
| `/var/run/docker.sock` | `/var/run/docker.sock` | Seguir controlando Docker y k3d (contenedores, `k3d node`, etc.) desde dentro del contenedor |
|
| `/var/run/docker.sock` | `/var/run/docker.sock` | Seguir controlando Docker y k3d (contenedores, `k3d node`, etc.) desde dentro del contenedor |
|
||||||
| `/DATA/AppData/k3d-lab-v3/claude-code-home` | `/root/.claude` | Persistir login/config de Claude Code — sobrevive no solo a un `docker restart`, sino a recrear el contenedor entero |
|
| `/DATA/AppData/k3d-lab-v3/claude-code-home` | `/root/.claude` | Persistir login/config de Claude Code — sobrevive no solo a un `docker restart`, sino a recrear el contenedor entero |
|
||||||
|
|
||||||
|
## Gotcha: el symlink `/DATA/AppData`
|
||||||
|
|
||||||
|
Montar `-v /DATA:/DATA` **no alcanza** para ver los repos dentro del
|
||||||
|
contenedor. `/DATA/AppData` en el host es un symlink *absoluto*:
|
||||||
|
|
||||||
|
```
|
||||||
|
/DATA/AppData -> /media/HDD-Storage/AppData
|
||||||
|
```
|
||||||
|
|
||||||
|
Los repos del lab (`lab-cruzcloud`) viven físicamente en el disco
|
||||||
|
btrfs `/media/HDD-Storage`, no en el ext4 de `/DATA` — ZimaOS lo
|
||||||
|
expone dentro de `/DATA` como submount (`/DATA/.media/HDD-Storage/...`,
|
||||||
|
que sí viaja al contenedor porque Docker hace bind recursivo por
|
||||||
|
defecto) pero el path "bonito" `/DATA/AppData/...` que usan `CLAUDE.md`
|
||||||
|
y todos los scripts del lab llega ahí vía ese symlink absoluto, no vía
|
||||||
|
el submount. Un symlink absoluto que apunta fuera del árbol montado
|
||||||
|
queda roto dentro del contenedor aunque el submount subyacente esté
|
||||||
|
perfectamente accesible por otra ruta.
|
||||||
|
|
||||||
|
**Cómo se detectó:** todo el trabajo de configuración inicial de este
|
||||||
|
mismo setup se hizo con `git`/`docker exec` corriendo *en el host*, no
|
||||||
|
dentro del contenedor — nadie había probado `cd
|
||||||
|
/DATA/AppData/k3d-lab-v3/lab-cruzcloud` desde una sesión `lab` real
|
||||||
|
hasta que se preguntó explícitamente por esto. `ls` devolvía "No such
|
||||||
|
file or directory" pese a que el volumen de `/DATA` estaba montado y
|
||||||
|
"andando".
|
||||||
|
|
||||||
|
**Fix:** montar también `-v /media/HDD-Storage:/media/HDD-Storage`,
|
||||||
|
para que el symlink resuelva exactamente igual que en el host.
|
||||||
|
|
||||||
|
## Gotcha: git "dubious ownership" dentro del contenedor
|
||||||
|
|
||||||
|
Con el mount anterior ya arreglado, `git status`/`git log` dentro del
|
||||||
|
contenedor fallan con:
|
||||||
|
|
||||||
|
```
|
||||||
|
fatal: detected dubious ownership in repository at '/media/HDD-Storage/...'
|
||||||
|
```
|
||||||
|
|
||||||
|
Los archivos en `/DATA`/`/media/HDD-Storage` pertenecen al usuario
|
||||||
|
`devops` del host (via samba), pero los procesos dentro del
|
||||||
|
contenedor corren como `root` (UID 0) — git, desde la versión que
|
||||||
|
introdujo la protección CVE-2022-24765, rechaza operar sobre un repo
|
||||||
|
cuyo dueño no coincide con el UID del proceso, a menos que el path
|
||||||
|
esté explícitamente marcado como seguro.
|
||||||
|
|
||||||
|
**Fix:** `git config --global --add safe.directory '*'` dentro del
|
||||||
|
contenedor. El wildcard (en vez de listar cada repo) es intencional
|
||||||
|
acá: este contenedor ya tiene acceso root-equivalente al host vía el
|
||||||
|
volumen de `/var/run/docker.sock`, así que restringir `safe.directory`
|
||||||
|
por repo no suma aislamiento real.
|
||||||
|
|
||||||
|
**Por qué está en el comando de arranque y no como paso manual
|
||||||
|
aparte:** igual que los paquetes `apk`, esta configuración vive en el
|
||||||
|
filesystem efímero del contenedor (`/root/.gitconfig`, que no está
|
||||||
|
bajo el volumen de `/root/.claude`) — se perdería si el contenedor se
|
||||||
|
recrea. Ponerla en el `sh -c` de arranque la deja recreándose sola
|
||||||
|
cada vez, sin pasos manuales que recordar.
|
||||||
|
|
||||||
Sobre paquetes: alpine (imagen `alpine` sin pin de versión, la misma
|
Sobre paquetes: alpine (imagen `alpine` sin pin de versión, la misma
|
||||||
que uso este setup) sí trae `kubectl` en sus repos — no hizo falta
|
que uso este setup) sí trae `kubectl` en sus repos — no hizo falta
|
||||||
cambiar de imagen base ni instalarlo por binario aparte, contrario a
|
cambiar de imagen base ni instalarlo por binario aparte, contrario a
|
||||||
@@ -119,3 +180,10 @@ un archivo de prueba escrito en `/root/.claude` dentro del contenedor
|
|||||||
apareció de inmediato en
|
apareció de inmediato en
|
||||||
`/DATA/AppData/k3d-lab-v3/claude-code-home` en el host, confirmando
|
`/DATA/AppData/k3d-lab-v3/claude-code-home` en el host, confirmando
|
||||||
el bind mount de credenciales.
|
el bind mount de credenciales.
|
||||||
|
|
||||||
|
Después de agregar el mount de `/media/HDD-Storage` y el
|
||||||
|
`safe.directory`, se validó además: `md5sum` de `CLAUDE.md` idéntico
|
||||||
|
leído desde el host y desde dentro del contenedor (vía el path con
|
||||||
|
symlink `/DATA/AppData/...`), y `git log`/`git status` corriendo sin
|
||||||
|
error sobre `apps-registry` y `scripts` desde una shell dentro de
|
||||||
|
`tmux-host`.
|
||||||
Reference in new issue
Block a user