diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..ca3feff67 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,31 @@ +# This file should remain in sync with .gitignore. If you need to make changes, +# please add a comment explaining why. For items that must be removed, comment +# them out instead of deleting them. +__pycache__/ +*.py[cod] +/output/ +/input/ +# This file prevents the image from building and would be overwritten by the +# /data volume in any case. +#!/input/example.png +/models/ +/temp/ +/custom_nodes/ +!custom_nodes/example_node.py.example +extra_model_paths.yaml +/.vs +.vscode/ +.idea/ +venv/ +.venv/ +/web/extensions/* +!/web/extensions/logging.js.example +!/web/extensions/core/ +/tests-ui/data/object_info.json +/user/ +*.log +web_custom_versions/ +.DS_Store +openapi.yaml +filtered-openapi.yaml +uv.lock diff --git a/.gitattributes b/.gitattributes index 5b3c15bb4..c68ee9205 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,6 @@ /web/assets/** linguist-generated /web/** linguist-vendored comfy_api_nodes/apis/__init__.py linguist-generated +# Force LF eol for Docker entrypoint (fix "exec: no such file or directory" +# error with CRLF checkouts) +entrypoint.sh text eol=lf diff --git a/.gitignore b/.gitignore index 4e8cea71e..847bfe03a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# If you modify this file, remember to update .dockerignore as well. __pycache__/ *.py[cod] /output/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..ccdaa4be3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,85 @@ +# Docker buildfile for the ComfyUI image, with support for hardware +# acceleration, file ownership synchronization, custom nodes, and custom node +# managers. + +# While Python 3.13 is well supported by ComfyUI, some older custom node packs +# may not work correctly with this version, which is why we're staying on Python +# 3.12 for now. +# +# Users are free to try different base Python image tags (e.g., 3.13, alpine, +# *-slim), but for maintainability, only one base version is officially +# supported at a time. +FROM python:3.12.12-trixie + +# Install cmake, which is an indirect installation dependencies +RUN apt-get update && apt-get install -y --no-install-recommends cmake + +# Create a regular user whose UID and GID will match the host user's at runtime. +# Also create a home directory for this user (-m), as some common Python tools +# (such as uv) interact with the user’s home directory. +RUN useradd -m comfyui + +# Install ComfyUI under /comfyui and set folder ownership to the comfyui user. +# With the legacy Docker builder (DOCKER_BUILDKIT=0), WORKDIR always creates missing +# directories as root (even if a different USER is active). To ensure the comfyui user +# can write inside, ownership must be fixed manually. +WORKDIR /comfyui +RUN chown comfyui:comfyui . + +# Install ComfyUI as ComfyUI +USER comfyui + +# Set up a Python virtual environment and configure it as the default Python. +# +# Reasons for using a virtual environment: +# - Some custom nodes use third-party tools like uv, which do not support +# user-level installations. +# - Custom node managers may install or update dependencies as the regular user, +# so a global installation is not an option. +# This leaves virtual environments as the only viable choice. +RUN python -m venv .venv +ENV PATH="/comfyui/.venv/bin:$PATH" + +# Install ComfyUI's Python dependencies. Although dependency keeping is also +# performed at startup, building ComfyUI's base dependencies into the image +# significantly speeds up each containers' first run. +# +# Since this step takes a long time to complete, it's performed early to take +# advantage of Docker's build cache, thereby accelerating subsequent builds. +COPY requirements.txt manager_requirements.txt ./ +RUN pip install --no-cache-dir --disable-pip-version-check \ + -r requirements.txt + +# Install ComfyUI +COPY . . + +# Purely declarative: inform Docker and image users that this image is designed +# to listen on port 8188 for the web GUI. +EXPOSE 8188 + +# Declare persistent volumes. We assign one volume per data directory to match +# ComfyUI’s natural file layout and to let users selectively choose which +# directories they want to mount. +VOLUME /comfyui/.venv +VOLUME /comfyui/custom_nodes +VOLUME /comfyui/input +VOLUME /comfyui/models +VOLUME /comfyui/output +VOLUME /comfyui/temp +VOLUME /comfyui/user +VOLUME /home/comfyui + +# Switch back to root to run the entrypoint and to install additional system +# dependencies +USER root + +# Configure entrypoint +RUN chmod +x entrypoint.sh +ENTRYPOINT [ "./entrypoint.sh" ] +CMD [ "python", "./main.py" ] + +# Install additional system dependencies +ARG APT_EXTRA_PACKAGES +RUN apt-get install -y --no-install-recommends $APT_EXTRA_PACKAGES \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index e25f3cda7..8ac4cfa36 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,12 @@ ComfyUI lets you design and execute advanced stable diffusion pipelines using a - Get the latest commits and completely portable. - Available on Windows. +#### [Docker Install](#running-with-docker) +- Run ComfyUI inside an isolated Docker container +- Most secure way to run ComfyUI and custom node packs +- Requires Docker and Docker Compose +- Supports NVIDIA GPUs (Not tested on other hardware.) + #### [Manual Install](#manual-install-windows-linux) Supports all operating systems and GPU types (NVIDIA, AMD, Intel, Apple Silicon, Ascend). @@ -350,6 +356,28 @@ For models compatible with Iluvatar Extension for PyTorch. Here's a step-by-step | `--enable-manager-legacy-ui` | Use the legacy manager UI instead of the new UI (requires `--enable-manager`) | | `--disable-manager-ui` | Disable the manager UI and endpoints while keeping background features like security checks and scheduled installation completion (requires `--enable-manager`) | +## Running with Docker + +Start by installing Docker, Docker Compose, and the NVIDIA Container Toolkit on +your host. Next, edit `compose.yaml` and update the `UID` and `GID` variables to +match your user. Additional fields are documented in the file for further +customization. + +Once ready, build and run the image locally: + +```shell +# (Re)build the Docker image. Run this before the first start, after updating +# ComfyUI, or after changing any build arguments in `compose.yaml`. +docker compose build +# Start ComfyUI. This reuses the most recently built image. +docker compose up +``` + +To stop and remove the container along with its volumes, run: + +```shell +docker compose down -v +``` # Running diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 000000000..d242b05a4 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,46 @@ +# Docker Compose file to run ComfyUI locally using Docker. + +services: + comfyui: + container_name: comfyui + build: + context: . + args: + # Declare additional system dependencies for custom nodes + APT_EXTRA_PACKAGES: + + ports: + - 8188:8188 + + # Optional: enable GPU access for hardware acceleration. + deploy: + resources: + reservations: + devices: + - capabilities: [gpu] + volumes: + - ./custom_nodes:/comfyui/custom_nodes + - ./models:/comfyui/models + + # (Optional) Mount host ComfyUI data directories + # + #- ./input:/comfyui/input + #- ./output:/comfyui/output + #- ./temp:/comfyui/temp + #- ./user:/comfyui/user + + environment: + # Overwrite the container user's UID and GID to match the host's. This + # allows files created by ComfyUI to be mounted on the host without + # permission issues. + UID: 1000 + GID: 1000 + # Declare additional Python packages to install. Useful when a custom node + # pack does not properly specify all its dependencies or relies on + # optional dependencies. + PIP_EXTRA_PACKAGES: + + # Optional: Override the default command. In this case, configure ComfyUI to + # listen on all network interfaces (which is required when not using + # `network_mode=host`.) + command: python ./main.py --listen 0.0.0.0 diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 000000000..37e576452 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# Entrypoint script for the ComfyUI Docker image. + +set -e + +user="comfyui" +user_group="$user" + +# Allow users to specify a UID and GID matching their own, so files created +# inside the container retain the same numeric ownership when mounted on the +# host. +if [ -n "$UID" ] && [ -n "$GID" ]; then + echo "[entrypoint] Setting user UID and GID..." + usermod -u "$UID" "$user" > /dev/null + groupmod -g "$GID" "$user_group" +else + echo "[entrypoint] Missing UID or GID environment variables; keeping default values." +fi + +# Changing a user's UID and GID revokes that user's access to files owned by the +# original UID/GID. To preserve access to runtime data, the ownership of those +# directories must be updated recursively so that their numeric owner matches +# the user's new UID and GID. +echo "[entrypoint] Changing directory ownership..." +chown -R "$user:$user_group" \ + /comfyui \ + /home/comfyui + +# To use CUDA and other NVIDIA features, regular users must belong to the group +# that owns the /dev/nvidia* device files -- typically the video group. +# +# Known issue: Because these device files are mounted from the host system, +# there's no guarantee that the device's group ID will match the intended group +# inside the container. For example, the video group might be mapped to GID 27 +# on the host, which corresponds to the sudo group in the python:3.12 image. +# This shouldn't cause major problems, and given the lack of a universal +# standard for system GIDs, there isn't much we can realistically change to +# address this issue. +echo "[entrypoint] Adding user to GPU device groups..." +for dev in /dev/nvidia*; do + group=$(ls -ld "$dev" | awk '{print $4}') + usermod -aG "$group" "$user" +done + +# Install or update the Python dependencies defined by ComfyUI (or any installed +# custom node) and also install any user-defined dependencies specified in +# PIP_EXTRA_PACKAGES. +echo "[entrypoint] Updating Python dependencies..." +su -c " + pip install \\ + --no-cache-dir \\ + --disable-pip-version-check \\ + -r requirements.txt \\ + $(find custom_nodes -mindepth 2 -maxdepth 2 -type f -name requirements.txt -printf "-r '%p' ") \\ + $PIP_EXTRA_PACKAGES +" comfyui \ + || echo "[entrypoint] Failed to install dependencies, starting anyway" >&2 + +# Run command as comfyui +echo "[entrypoint] Running command" +exec su -c "$*" comfyui