diff --git a/src/everything/Dockerfile b/src/everything/Dockerfile index 6729298b06..605e3b7b90 100644 --- a/src/everything/Dockerfile +++ b/src/everything/Dockerfile @@ -19,4 +19,6 @@ ENV NODE_ENV=production RUN npm ci --ignore-scripts --omit-dev +USER node + CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/fetch/Dockerfile b/src/fetch/Dockerfile index d2a4504931..c0db52b5e0 100644 --- a/src/fetch/Dockerfile +++ b/src/fetch/Dockerfile @@ -26,6 +26,12 @@ FROM python:3.12-slim-bookworm WORKDIR /app COPY --from=uv /root/.local /root/.local +# /root defaults to 700, which blocks any non-root user from even traversing +# into /root/.local — and the venv's own python binary is a symlink into +# /root/.local/share/uv/python/.../bin/python3.11, resolved at every startup, +# not just at build time. Without this, switching to a non-root USER below +# breaks the interpreter itself, not just file access. +RUN chmod o+rx /root RUN if ! id -u app >/dev/null 2>&1; then \ useradd -rUM -s /usr/sbin/nologin app; \ @@ -35,5 +41,7 @@ COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" +USER app + # when running the container, add --db-path and a bind mount to the host's db file ENTRYPOINT ["mcp-server-fetch"] diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile index 418b140056..c8d3e0caeb 100644 --- a/src/filesystem/Dockerfile +++ b/src/filesystem/Dockerfile @@ -22,4 +22,6 @@ ENV NODE_ENV=production RUN npm ci --ignore-scripts --omit-dev +USER node + ENTRYPOINT ["node", "/app/dist/index.js"] \ No newline at end of file diff --git a/src/git/Dockerfile b/src/git/Dockerfile index 4af41612c7..ae7c6e1804 100644 --- a/src/git/Dockerfile +++ b/src/git/Dockerfile @@ -29,6 +29,12 @@ RUN apt-get update && apt-get install -y git git-lfs && rm -rf /var/lib/apt/list WORKDIR /app COPY --from=uv /root/.local /root/.local +# /root defaults to 700, which blocks any non-root user from even traversing +# into /root/.local — and the venv's own python binary is a symlink into +# /root/.local/share/uv/python/.../bin/python3.11, resolved at every startup, +# not just at build time. Without this, switching to a non-root USER below +# breaks the interpreter itself, not just file access. +RUN chmod o+rx /root RUN if ! id -u app >/dev/null 2>&1; then \ useradd -rUM -s /usr/sbin/nologin app; \ @@ -38,5 +44,13 @@ COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" +# The container's job is exclusively to operate on whichever repo is bind-mounted +# in, so there's no meaningful "wrong owner" for git to protect against here the +# way there is on a shared host; without this, git refuses to touch a repo owned +# by a different uid than the app user once we stop running as root below. +RUN git config --system --add safe.directory '*' + +USER app + # when running the container, add --db-path and a bind mount to the host's db file ENTRYPOINT ["mcp-server-git"] diff --git a/src/memory/Dockerfile b/src/memory/Dockerfile index 2f85d0cfa2..1490f31e64 100644 --- a/src/memory/Dockerfile +++ b/src/memory/Dockerfile @@ -21,4 +21,12 @@ WORKDIR /app RUN npm ci --ignore-scripts --omit-dev +# Without MEMORY_FILE_PATH set, the server persists its knowledge graph next +# to its own compiled entrypoint (dist/memory.jsonl) — dist was just copied in +# as root, so the app user needs ownership of it before it can create/update +# that file, including when a named volume (see README) mounts over dist/. +RUN chown -R node:node /app/dist + +USER node + ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/sequentialthinking/Dockerfile b/src/sequentialthinking/Dockerfile index f1a88195bc..db9afb7eb8 100644 --- a/src/sequentialthinking/Dockerfile +++ b/src/sequentialthinking/Dockerfile @@ -21,4 +21,6 @@ WORKDIR /app RUN npm ci --ignore-scripts --omit-dev +USER node + ENTRYPOINT ["node", "dist/index.js"] diff --git a/src/time/Dockerfile b/src/time/Dockerfile index c92873277d..f8ede3f8cc 100644 --- a/src/time/Dockerfile +++ b/src/time/Dockerfile @@ -26,6 +26,12 @@ FROM python:3.12-slim-bookworm WORKDIR /app COPY --from=uv /root/.local /root/.local +# /root defaults to 700, which blocks any non-root user from even traversing +# into /root/.local — and the venv's own python binary is a symlink into +# /root/.local/share/uv/python/.../bin/python3.11, resolved at every startup, +# not just at build time. Without this, switching to a non-root USER below +# breaks the interpreter itself, not just file access. +RUN chmod o+rx /root RUN if ! id -u app >/dev/null 2>&1; then \ useradd -rUM -s /usr/sbin/nologin app; \ @@ -38,5 +44,7 @@ ENV PATH="/app/.venv/bin:$PATH" # Set the LOCAL_TIMEZONE environment variable ENV LOCAL_TIMEZONE=${LOCAL_TIMEZONE:-"UTC"} +USER app + # when running the container, add --local-timezone and a bind mount to the host's db file ENTRYPOINT ["mcp-server-time", "--local-timezone", "${LOCAL_TIMEZONE}"]