Files
BoosAPI/docker/Dockerfile.comfyui.multi-tenant
T
2026-05-21 16:32:04 +02:00

125 lines
6.5 KiB
Docker

# syntax=docker/dockerfile:1.4
# Multi-tenant ComfyUI image — one container per BoosAPI user.
#
# Lineage: based on the same Python 3.11 / CPU-only profile the legacy
# bosapi-comfyui:ready image used. Differences from the singleton image:
# 1. Bakes `comfy_patches/overlay` into the image (proxy-base
# default + auth-header fallback, server/runtime hardening, docs)
# so containers do NOT need a host bind-mount of `comfy_source/`.
# 2. Bakes the BoosAPI custom nodes from `comfy/boosapi_comfy_nodes.py`
# under `/workspace/ComfyUI/custom_nodes/` so workflows referencing
# `BoosAPITextGen` etc. resolve without any host mount.
# 3. Reads `BOOSAPI_BUILTIN_KEY`, `BOOSAPI_BASE`, `BOOSAPI_KEY` at
# runtime via the entrypoint shim and forwards them as
# `--comfy-api-base` and the documented env vars.
# 4. No host source mounts — all ComfyUI code lives inside the image
# so the container can run with `--read-only` and tmpfs `/tmp`.
#
# Build context MUST be the repo root (`docker build -f docker/Dockerfile.comfyui.multi-tenant .`).
#
# Requires BuildKit (Docker 20.10+ has it on by default; build-and-run.sh
# also exports DOCKER_BUILDKIT=1 defensively). The `--mount=type=cache`
# instructions below are no-ops without BuildKit.
FROM python:3.11-slim
WORKDIR /workspace
# USTC mirror for faster apt
RUN sed -i 's|deb.debian.org|mirrors.ustc.edu.cn|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \
sed -i 's|deb.debian.org|mirrors.ustc.edu.cn|g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl tini \
&& rm -rf /var/lib/apt/lists/*
# uv: 5-10x faster than pip on resolution + install. Installed from PyPI
# via the Tsinghua mirror that's already used by the rest of the build,
# instead of curling the upstream GitHub release tarball —
# `github.com/astral-sh/uv/releases/...` is unreliable from mainland
# networks (TLS handshake completes, then body read truncates with
# `SSL_read: unexpected eof`). The PyPI wheel bundles the same self-
# contained binary and drops `uv` into the system Python's scripts dir
# (already on PATH). Pinned for reproducibility.
RUN pip install --no-cache-dir \
--index-url https://pypi.tuna.tsinghua.edu.cn/simple \
uv==0.5.31 \
&& uv --version
# ── Layer-caching strategy ────────────────────────────────────────────
# Copy ONLY requirements.txt first. The heavy install layers (torch +
# ComfyUI deps, ~200 MB combined) then live in their own cache lines
# that only invalidate when requirements.txt actually changes. Most
# rebuilds change other comfy_source/ files (workflow scripts, custom
# nodes, etc.), so this swap turns a 5-10 minute reinstall into a
# zero-network layer-cache hit.
#
# The full `COPY comfy_source` happens after the install. It overlays
# the rest of ComfyUI on top of the venv directory (which lives at
# /workspace/ComfyUI/venv) without disturbing it — venv/ isn't present
# in the source tree, and requirements.txt is just rewritten with
# identical content.
COPY comfy_source/requirements.txt /workspace/ComfyUI/requirements.txt
WORKDIR /workspace/ComfyUI
RUN uv venv venv --python python3.11
ENV PATH="/workspace/ComfyUI/venv/bin:${PATH}"
# ── PyTorch CPU wheels ────────────────────────────────────────────────
# ~200 MB combined and the single biggest network draw of the build.
# Two reliability levers:
# 1. Tsinghua pytorch-wheels mirror replaces upstream
# `download.pytorch.org/whl/cpu`. Upstream is slow + flaky from
# mainland networks (TLS handshake completes, body read truncates
# with `SSL_read: unexpected eof`). Tsinghua mirrors the same
# wheels and is documented as a drop-in `--extra-index-url`.
# 2. BuildKit cache mount on /root/.cache/uv preserves the downloaded
# wheels across rebuilds. Even if this layer is invalidated (e.g.
# after a torch version bump), uv reuses cached wheels and only
# fetches what changed.
RUN --mount=type=cache,target=/root/.cache/uv \
UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
UV_EXTRA_INDEX_URL=https://mirrors.tuna.tsinghua.edu.cn/pytorch-wheels/cpu/ \
uv pip install --python venv/bin/python torch torchvision torchaudio
# ── ComfyUI deps ──────────────────────────────────────────────────────
# kornia_rs is a Rust-built wheel that compiles from source on install,
# adding minutes to the build. The BoosAPI workflows we care about
# don't use it, so strip it. Cache mount handles re-downloads when
# requirements.txt changes (most lines stay the same → most wheels
# reuse from cache).
RUN --mount=type=cache,target=/root/.cache/uv \
grep -v kornia_rs requirements.txt > /tmp/requirements.txt && \
UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
uv pip install --python venv/bin/python -r /tmp/requirements.txt && \
UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
uv pip install --python venv/bin/python six && \
rm /tmp/requirements.txt
# ── Full ComfyUI source ───────────────────────────────────────────────
# This overlay COPY brings in everything else under comfy_source/. The
# venv at /workspace/ComfyUI/venv survives because the source tree
# doesn't contain a venv/ directory; requirements.txt is overwritten
# with identical bytes (no-op).
COPY comfy_source /workspace/ComfyUI
RUN git init
# ── Bake the BoosAPI patches ──────────────────────────────────────────
# Keep the image self-contained: overlay patches are tracked in the parent
# repo, while comfy_source remains a vanilla ComfyUI submodule.
COPY comfy_patches/overlay /workspace/ComfyUI
# BoosAPI custom nodes (BoosAPITextGen, image gen, etc.).
RUN mkdir -p /workspace/ComfyUI/custom_nodes/boosapi_nodes
COPY comfy/boosapi_comfy_nodes.py \
/workspace/ComfyUI/custom_nodes/boosapi_nodes/__init__.py
# Entrypoint shim — forwards env vars to ComfyUI's CLI flags.
COPY docker/comfyui-entrypoint.sh /usr/local/bin/comfyui-entrypoint
RUN chmod +x /usr/local/bin/comfyui-entrypoint
EXPOSE 8188
# tini reaps any subprocesses ComfyUI spawns; the shim execs into Python.
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/comfyui-entrypoint"]