diff --git a/docker/DockerfileExtra b/docker/DockerfileExtra index 190f65caba..b0e4bd8ad7 100644 --- a/docker/DockerfileExtra +++ b/docker/DockerfileExtra @@ -124,10 +124,19 @@ WORKDIR /app COPY docker/entrypoint-extra.sh /entrypoint.sh RUN chmod +x /entrypoint.sh -# Set permissions -RUN chmod -R a+rX /usr/local && \ - chmod -R a+rX /pyls && \ - chmod -R a+rX /debugger +# Non-root 'windmill' user with UID/GID 1000 to match the app image, so +# `runAsUser: 1000` resolves to a real account with a writable $HOME. +# No USER directive: the image still starts as root by default. +RUN addgroup --gid 1000 windmill && \ + adduser --disabled-password --gecos "" --uid 1000 --gid 1000 windmill + +# The root-run installs above write into the base image's UV_CACHE_DIR +# (/tmp/windmill/cache/uv) after the base already made it world-writable, leaving +# root-owned 0755 dirs that make uv fail EACCES for a non-root UID. /pyls/.cache +# (XDG_CACHE_HOME, incl. DENO_DIR) and /tmp/monaco are written at runtime too. +RUN chmod -R a+rX /usr/local /pyls /debugger /multiplayer /tmp/monaco && \ + chmod -R a+rw /tmp/windmill /pyls/.cache && \ + find /tmp/windmill /pyls/.cache /tmp/monaco -type d -exec chmod 777 {} + # Expose all service ports EXPOSE 3000 3001 3002 3003 diff --git a/docker/entrypoint-extra.sh b/docker/entrypoint-extra.sh index 385db124fb..a06901e25c 100644 --- a/docker/entrypoint-extra.sh +++ b/docker/entrypoint-extra.sh @@ -21,16 +21,29 @@ cleanup() { trap cleanup SIGTERM SIGINT +# An arbitrary non-root UID gets HOME=/ and cannot write the image's 0700 /root, so +# redirect $HOME before anything writes under it (netrc below, plus the bun/npm/go +# caches in the services). Keep the fallback UID-scoped: a leftover dir from a +# different UID on a shared /tmp is not writable. Root keeps HOME=/root. +HOME="${HOME:-/root}" +if [ ! -w "$HOME" ]; then + echo "[entrypoint] HOME=$HOME is not writable for UID $(id -u), using HOME=/tmp/windmill-home-$(id -u)" + HOME="/tmp/windmill-home-$(id -u)" + mkdir -p "$HOME" +fi +export HOME + # Setup NETRC if provided (for LSP) if [ -n "$NETRC" ]; then - echo "$NETRC" > /root/.netrc - chmod 600 /root/.netrc + echo "$NETRC" > "$HOME/.netrc" + chmod 600 "$HOME/.netrc" fi -# Setup cache directory for LSP -if [ -d /root/.cache ]; then - export XDG_CACHE_HOME=/root/.cache - cp -r /pyls/.cache /root/.cache 2>/dev/null || true +# Setup cache directory for LSP (falls back to the image's world-writable +# XDG_CACHE_HOME=/pyls/.cache when $HOME/.cache isn't mounted) +if [ -d "$HOME/.cache" ]; then + export XDG_CACHE_HOME="$HOME/.cache" + cp -r /pyls/.cache "$HOME/.cache" 2>/dev/null || true fi # Setup Monaco temp directory for LSP