Ctrl K
ComunidadGuías…

Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
FROM node:24-slim

# ttyd is not packaged for Debian - the upstream release binary is static
# and published per architecture, which is cheaper than building
# libwebsockets in here.
ARG TTYD_VERSION=1.7.7
ARG TARGETARCH

# git, because the repositories a session works on are the point of this
# image and Claude Code's core workflows need it - node:24-slim carries none.
RUN apt-get update \
    && apt-get install -y --no-install-recommends tmux ca-certificates curl git procps \
    && rm -rf /var/lib/apt/lists/* \
    # Pinned by content, not only by tag: a release asset can be replaced
    # under its tag, and strangers run this image. The hashes belong to
    # TTYD_VERSION above and move with it.
    && case "$TARGETARCH" in \
         amd64) ttyd_arch=x86_64 ttyd_sha=8a217c968aba172e0dbf3f34447218dc015bc4d5e59bf51db2f2cd12b7be4f55 ;; \
         arm64) ttyd_arch=aarch64 ttyd_sha=b38acadd89d1d396a0f5649aa52c539edbad07f4bc7348b27b4f4b7219dd4165 ;; \
         *) echo "unsupported architecture: $TARGETARCH" >&2; exit 1 ;; \
       esac \
    && curl -fsSL "https://github.com/tsl0922/ttyd/releases/download/${TTYD_VERSION}/ttyd.${ttyd_arch}" -o /usr/local/bin/ttyd \
    && echo "${ttyd_sha}  /usr/local/bin/ttyd" | sha256sum -c - \
    && chmod +x /usr/local/bin/ttyd \
    && npm install -g @anthropic-ai/claude-code

# Anyone who reaches the port gets a shell as this user - the same reason
# deploy/claudux.service sets User=. The container default would be root.
#
# uid 1000, which the base image's own `node` user holds and therefore gives
# up here: a host user at 1000 has to stay able to write the files under a
# mounted -v ~/code:/projects. --create-home leaves /home/claudux to
# claudux, so the volume the README mounts there inherits that ownership and
# the app creates .claudux under it on first write.
RUN userdel -r node \
    && useradd --create-home --uid 1000 --shell /bin/bash claudux \
    # So the documented volume mount target exists with the right
    # ownership even before anything is actually mounted there.
    && mkdir -p /projects \
    && chown claudux:claudux /projects
WORKDIR /app
# Deliberately no --chown: /app stays root-owned, so a session cannot
# rewrite the code the next container start runs. npm ci runs as root here
# either way.
COPY . .
RUN npm ci --omit=dev

USER claudux

# USER does not set HOME, and config.js resolves every per-installation path
# through os.homedir() - which reads $HOME first. Left to the runtime it is
# either unset or still /root, and the second case is unwritable.
ENV HOME=/home/claudux
EXPOSE 4001
CMD ["node", "src/server.js"]