From f2816aadf36f4177692719f11b84242a83c1b17d Mon Sep 17 00:00:00 2001 From: Brian Gebel Date: Wed, 11 Mar 2026 07:03:42 -0700 Subject: [PATCH 1/2] feat: robust arbitrary UID support for non-root containers Enable running the image as any UID (e.g., K8s securityContext.runAsUser) without prior configuration: - Dynamically inject /etc/passwd entry for unknown UIDs in the entrypoint so getpwuid(), getpass.getuser(), and expanduser("~") work correctly (standard practice per OpenShift arbitrary UID guidelines) - Make /etc/passwd group-writable at build time for runtime injection - Make /app/.cache world-writable for uv/pip cache operations - Document arbitrary UID support in running guide Co-Authored-By: Claude Opus 4.6 --- docs/user-guides/running.md | 8 ++++++-- services/comfy/core/dockerfile.comfy.core | 11 ++++++++--- services/comfy/core/entrypoint.sh | 10 ++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/user-guides/running.md b/docs/user-guides/running.md index 3ea1884..05bc028 100644 --- a/docs/user-guides/running.md +++ b/docs/user-guides/running.md @@ -173,9 +173,13 @@ spec: No PUID/PGID environment variables are needed in this mode — the UID/GID comes from the Kubernetes security context. The `fsGroup` setting ensures volume mounts are group-accessible. -### File Ownership +### Arbitrary UID Support -At build time, all application files under `/app` are owned by a `comfy` user (UID 1000). The venv `site-packages` directory is world-writable so that ComfyUI Manager can install custom node dependencies at runtime regardless of the effective UID. +The image supports running as any UID without prior configuration: + +- **`/etc/passwd` injection**: The entrypoint dynamically adds a passwd entry for unknown UIDs so that Python's `getpass.getuser()`, `os.path.expanduser("~")`, and PyTorch's cache directory resolution all work correctly. +- **World-writable directories**: `site-packages`, `.cache` are writable by any UID at build time so ComfyUI Manager can install custom node dependencies and uv/pip can cache packages. +- **File ownership**: All files under `/app` are owned by the `comfy` user (UID 1000) at build time. Runtime file creation in mounted volumes uses the effective UID. ### Verification diff --git a/services/comfy/core/dockerfile.comfy.core b/services/comfy/core/dockerfile.comfy.core index a4a6fbd..ad31650 100644 --- a/services/comfy/core/dockerfile.comfy.core +++ b/services/comfy/core/dockerfile.comfy.core @@ -64,11 +64,16 @@ COPY --chown=comfy:comfy startup.sh entrypoint.sh /app/ # Make scripts executable (fast/cheap operation on single files) RUN chmod +x /app/startup.sh /app/entrypoint.sh -# Make venv site-packages writable by any user so ComfyUI Manager can -# install custom node deps at runtime regardless of the effective UID +# Make directories writable by any user for arbitrary UID support # (Docker Compose PUID/PGID, K8s securityContext.runAsUser, etc.) +# - site-packages: ComfyUI Manager installs custom node deps at runtime +# - .cache: uv/pip cache operations +# - /etc/passwd: entrypoint injects passwd entry for arbitrary UIDs +# so getpwuid(), getpass.getuser(), and expanduser("~") work RUN chmod -R a+w /app/.venv/lib/python3.12/site-packages && \ - chmod a+w /app/.venv/lib/python3.12 + chmod a+w /app/.venv/lib/python3.12 && \ + chmod -R a+w /app/.cache && \ + chmod g+w /etc/passwd # Environment variables ARG CLI_ARGS="" diff --git a/services/comfy/core/entrypoint.sh b/services/comfy/core/entrypoint.sh index aa2719a..3d0a274 100755 --- a/services/comfy/core/entrypoint.sh +++ b/services/comfy/core/entrypoint.sh @@ -9,6 +9,16 @@ set -e # venv and exec directly — no privilege management needed. if [ "$(id -u)" -ne 0 ]; then echo "Starting as non-root UID:GID = $(id -u):$(id -g)" + + # Inject a passwd entry for the current UID if one doesn't exist. + # Many tools (Python's getpass.getuser(), PyTorch's cache_dir, + # os.path.expanduser) call getpwuid() which fails with KeyError + # for UIDs not in /etc/passwd. This is standard practice for + # containers supporting arbitrary UIDs (e.g., OpenShift). + if ! whoami &>/dev/null 2>&1; then + echo "comfy:x:$(id -u):$(id -g):ComfyUI User:/app:/bin/bash" >> /etc/passwd + fi + source /app/.venv/bin/activate exec "$@" fi From 3c0af3b4f9159074078202560236b4f02a48c8c2 Mon Sep 17 00:00:00 2001 From: Brian Gebel Date: Wed, 11 Mar 2026 16:03:01 -0700 Subject: [PATCH 2/2] fix: create .cache directory before chmod (not copied from builder) The /app/.cache directory was created during the builder stage via pip cache mount but wasn't included in COPY --from=builder. Use mkdir -p to ensure it exists before setting permissions. Co-Authored-By: Claude Opus 4.6 --- services/comfy/core/dockerfile.comfy.core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/comfy/core/dockerfile.comfy.core b/services/comfy/core/dockerfile.comfy.core index ad31650..f760585 100644 --- a/services/comfy/core/dockerfile.comfy.core +++ b/services/comfy/core/dockerfile.comfy.core @@ -72,7 +72,7 @@ RUN chmod +x /app/startup.sh /app/entrypoint.sh # so getpwuid(), getpass.getuser(), and expanduser("~") work RUN chmod -R a+w /app/.venv/lib/python3.12/site-packages && \ chmod a+w /app/.venv/lib/python3.12 && \ - chmod -R a+w /app/.cache && \ + mkdir -p /app/.cache && chmod -R a+w /app/.cache && \ chmod g+w /etc/passwd # Environment variables