Add local Docker support

This commit is contained in:
B. Bergeron 2025-08-12 19:32:28 -04:00
parent f8b981ae9a
commit 89fe38b79f
No known key found for this signature in database
GPG Key ID: 20A0A88F22238925
5 changed files with 234 additions and 0 deletions

31
.dockerignore Normal file
View File

@ -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

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
# If you modify this file, remember to update .dockerignore as well.
__pycache__/
*.py[cod]
/output/

84
Dockerfile Normal file
View File

@ -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 <me@bbergeron.xyz>
#
# 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 users 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 users 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/*

42
docker-compose.yml Normal file
View File

@ -0,0 +1,42 @@
# Docker Compose file to run ComfyUI locally using Docker.
#
# Authors:
# B. Bergeron <me@bbergeron.xyz>
#
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

76
entrypoint.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/sh
# Entrypoint script for the ComfyUI Docker image.
#
# Authors:
# B. Bergeron <me@bbergeron.xyz>
#
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