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/.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..99d7cc70b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,84 @@ +# Docker buildfile for the ComfyUI image, with support for hardware +# acceleration, file ownership synchronization, custom nodes, and custom node +# managers. +# +# Authors: +# B. Bergeron +# + +# Use the recommended Python version 3.12, as specified in the README. +FROM python:3.12.11-bookworm AS comfyui-base + +# Install cmake, which is an indirect installation dependencies +RUN apt update \ + && apt install -y --no-install-recommends cmake \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* + +# Create a mount point for user-generated data. +RUN mkdir -p \ + /data/input \ + /data/output \ + /data/temp \ + /data/user + +# 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 +USER comfyui + +# Install ComfyUI under /comfyui. +WORKDIR /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 Python dependencies. This step is also performed automatically by the +# entrypoint script, but doing it at build time reduces startup time on the +# first run. +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +# Install ComfyUI and link the data mount points. +COPY . . +RUN ln -sf /data/* . + +# 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: +# - /data: stores user-generated data from ComfyUI, +# - /comfyui/.venv: stores Python data generated by the entrypoint and custom +# node managers, +# - /comfyui/custom_nodes: stores custom nodes installed at runtime by custom +# node managers, +# - /home/comfyui: stores data from Python packages that may write outside the +# virtual environment and into the user’s home directory. +VOLUME [ "/data", "/comfyui/.venv", "/comfyui/custom_nodes", "/home/comfyui" ] + +# Switch back to root to run the entrypoint and ensure it is executable. +USER root +RUN chmod +x entrypoint.sh +ENTRYPOINT [ "./entrypoint.sh" ] +CMD [ "python", "./main.py" ] + +# Known issue: Some custom nodes require additional system dependencies, which +# are not as easy to install as Python dependencies. If this is the case, you +# can use the instruction below to install the required packages. +#RUN apt update \ +# && apt install -y --no-install-recommends \ +# package-1 \ +# package-2 \ +# ... \ +# && apt clean \ +# && rm -rf /var/lib/apt/lists/* diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..c6bf30456 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +# Docker Compose file to run ComfyUI locally using Docker. +# +# Authors: +# B. Bergeron +# + +services: + comfyui: + container_name: comfyui + build: . + + ports: + - 127.0.0.1:8188:8188 + + # Optional: enable GPU access for hardware acceleration. + deploy: + resources: + reservations: + devices: + - capabilities: [gpu] + volumes: + # Share custom nodes and models with the container. + - ./custom_nodes:/comfyui/custom_nodes + - ./models:/comfyui/models + # Optional: mount the user data directory. + #- data:/data/ + + 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..9b844eb1d --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# Entrypoint script for the ComfyUI Docker image. +# +# Authors: +# B. Bergeron +# + +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 + + +echo "[entrypoint] Changing directory ownership..." +chown -R "$user:$user_group" /data /comfyui/custom_nodes /comfyui/.venv /home/comfyui + +# Add the user to the groups owning /dev/nvidia* devices to ensure CUDA access. +# Typically, these devices belong to a single "video" group, but to be safe, we +# add the user to each device's group individually. +echo "[entrypoint] Adding user to GPU device groups..." +for dev in /dev/nvidia*; do + # Known issue: There is no universal standard for group IDs across Linux + # systems, so this may add the user to unexpected groups. For example, the + # 'video' group on some systems uses GID 27, which corresponds to 'sudo' in + # the python:3.12 image. This should not cause serious problems. + group=$(ls -ld "$dev" | awk '{print $4}') + usermod -aG "$group" "$user" +done + + +# Install packages listed in ./requirements.txt, requirement files under +# ./custom_nodes, and any specified in PIP_EXTRA_PACKAGES. Also store a hash of +# all dependencies to detect when new or updated packages need to be installed. +packages_hash_file="/home/comfyui/pkghash" + +packages_comfyui=$(cat requirements.txt) +packages_custom=$(find custom_nodes -name requirements.txt -exec cat {} \;) +packages_extras=$(echo "$PIP_EXTRA_PACKAGES" | tr ' ' '\n') + +current_hash=$( + { + echo "$packages_comfyui"; + echo "$packages_custom"; + echo "$packages_extras" + } | sort | sha256sum | awk '{print $1}' +) + +if [ ! -f "$packages_hash_file" ] || [ "$current_hash" != "$(cat $packages_hash_file)" ]; then + echo "[entrypoint] Installing new python dependencies..." + reqs="-r requirements.txt" + for req in custom_nodes/*/requirements.txt; do + [ -f "$req" ] && reqs="$reqs -r $req" + done + + su -c "pip install -q --disable-pip-version-check --no-cache-dir $reqs $PIP_EXTRA_PACKAGES" comfyui + echo "$current_hash" > "$packages_hash_file" +else + echo "[entrypoint] Requirements unchanged, skipping install" +fi + + +# Run command as comfyui +echo "[entrypoint] Running command" +exec su -c "$*" comfyui