6.9 KiB
Plan: Instalar Claude Code system-wide (username-agnostic, última versión) en el Dockerfile
Context
El Dockerfile instala Claude Code vía el repo apt oficial (claude-code,
líneas 147‑155) desde el commit 7096b11. Eso provocó dos problemas:
- Versión vieja: el canal apt
stableva por detrás del canallatest. En este contenedor hay2.1.197, mientras quelatestya está en2.1.207. - MCPs no cargan: verificado que es estructural, no de versión. El usuario declaró sus
MCPs (gitea, docmost, github-personal, penpot, atlassian) bajo la clave
mcpServersdentro de~/.claude/settings.json, pero Claude Code no leemcpServersdesdesettings.json.claude mcp listlo confirmó: solo aparecen los conectores de claude.ai, ninguno de los del usuario. Los MCPs de usuario viven en~/.claude.json(archivo hermano de.claude/, no dentro), en.mcp.jsonde proyecto, o en/etc/claude-code/managed-mcp.json(enterprise).
Intentos previos y por qué fallaron:
curl … install.sh | bash(commit original): deja el binario en~/.local/bindel usuario que instala (root) → inalcanzable para otros HOME_USER.HOME=/usr/local/claude … install.sh(be1a141): el binario resuelve su home por el registro del SO, ignoró el override y volvió a caer en/root.- apt
claude-code(7096b11): quedó en/usr/bin(bien para multi-usuario) pero atado al canalstabledesactualizado.
Objetivo: que claude esté disponible por defecto para cualquier nombre de usuario del
SO, siempre en la última versión, con auto-update en runtime funcionando, y sin depender
de trucos de $HOME/.bashrc.
Alcance (confirmado con el usuario)
- Este repo (Dockerfile): SOLO arreglar la instalación de Claude Code.
- MCPs: NO se toca la imagen. Se documenta la guía para que el usuario los reubique vía sus volúmenes (sección "Guía MCPs" abajo).
Enfoque recomendado
Descargar el binario nativo standalone directamente del canal oficial latest (el mismo artefacto
que install.sh usa internamente), verificar su checksum, y colocarlo en /usr/local/bin/claude
(modo 0755, root). Esa ruta ya está en el PATH por defecto de todo usuario (igual que gh,
kubectl, docker), así que es completamente independiente del nombre de usuario y no necesita
exports en .bashrc.
El auto-update en runtime sigue funcionando por usuario: el updater nativo descarga nuevas
versiones en el propio ~/.local/share/claude/versions/ de cada usuario, independiente del binario
root de /usr/local/bin. La línea existente export PATH="$HOME/.local/bin:$PATH" (línea 176)
hace que esa copia actualizada por usuario tome precedencia. El binario base de la imagen se
refresca además en cada build de CI.
Cambios en Dockerfile
1. Reemplazar el bloque apt (líneas 147‑155) por descarga directa del binario latest
python3 ya está disponible en esta etapa (viene de python3-pip), así que se usa para parsear el
manifest.json de forma robusta. El base es Debian/glibc → variante linux-<arch> (no musl).
# Installing Claude Code (system-wide, latest native build, accessible by any user)
# Pull the standalone native binary straight from the official 'latest' release
# channel (the same artifact install.sh uses internally) and drop it on the
# system PATH at /usr/local/bin -- already on every user's PATH, like gh/kubectl.
# Avoids install.sh's per-user ~/.local/bin layout (unreachable for other users)
# and the apt 'stable' channel lag that shipped an outdated build. Runtime
# auto-update still works per user: the native updater writes new versions into
# each user's own ~/.local/share/claude/versions.
RUN set -eux; \
case "$(dpkg --print-architecture)" in \
amd64) CC_ARCH=x64 ;; \
arm64) CC_ARCH=arm64 ;; \
*) echo "unsupported architecture: $(dpkg --print-architecture)" >&2; exit 1 ;; \
esac; \
CC_BASE="https://downloads.claude.ai/claude-code-releases"; \
CC_VERSION="$(curl -fsSL "${CC_BASE}/latest")"; \
CC_CHECKSUM="$(curl -fsSL "${CC_BASE}/${CC_VERSION}/manifest.json" \
| python3 -c "import sys,json;print(json.load(sys.stdin)['platforms']['linux-${CC_ARCH}']['checksum'])")"; \
curl -fsSL "${CC_BASE}/${CC_VERSION}/linux-${CC_ARCH}/claude" -o /tmp/claude; \
echo "${CC_CHECKSUM} /tmp/claude" | sha256sum -c -; \
sudo install -m 0755 -o root -g root /tmp/claude /usr/local/bin/claude; \
rm -f /tmp/claude; \
claude --version
2. Eliminar la línea de auto-update específica de apt (líneas 177‑178)
# Let Claude Code auto-upgrade its apt package in the background when a new version ships
RUN echo 'export CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1' | sudo tee -a /usr/bin/.bashrc
Ya no aplica (no es instalación apt). El auto-update nativo funciona por defecto sin esa env var.
Se conserva la línea 176 (export PATH="$HOME/.local/bin:$PATH") porque es de propósito
general y ayuda a que el claude auto-actualizado por usuario tome precedencia.
3. Bump de versión en README.md
1.4.1 → 1.4.2 (mismo patrón que los commits previos).
Guía MCPs (fuera de la imagen — lo aplica el usuario en sus volúmenes)
Causa raíz: mcpServers en ~/.claude/settings.json es ignorado. El resto de settings.json
(permissions, hooks, model, enabledPlugins, env, theme, etc.) sí es válido y se
queda ahí.
Pasos:
- Mover el bloque
mcpServersde~/.claude/settings.jsonal archivo~/.claude.json(en el HOME, hermano del directorio.claude/), como clave top-level:{ "mcpServers": { "gitea": { "type": "http", "url": "…", "headers": { … } }, "docmost": { … } } } - Persistir
~/.claude.jsonen el volumen por usuario, montado read-write (Claude reescribe ese archivo con historial de proyectos; no debe ser read-only). El volumen actual que monta~/.claude/no lo cubre porque~/.claude.jsonestá fuera de ese directorio. - Borrar el bloque
mcpServersobsoleto desettings.jsonpara evitar confusión.
Verificación
- Build:
docker build -t vscode-server:test .(o vía el workflow de Gitea). Confirmar que el nuevoRUNimprimeclaude --version=2.1.207(o superior) sin error de checksum. - Multi-arch: el
casecubre amd64/arm64; el build de CI eslinux/amd64,linux/arm64. - Username-agnostic: correr el contenedor y, como el usuario por defecto y como otro usuario
distinto, verificar
which claude→/usr/local/bin/claudey queclaude --versionresponde. - Auto-update runtime: tras un rato de uso, confirmar que aparece
~/.local/share/claude/versions/en el home del usuario (update nativo por usuario) sin permisos root. - MCPs (tras aplicar la guía en el volumen):
claude mcp listdebe listar gitea/docmost/ github-personal/penpot/atlassian comoConnected.