diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..21e56ed85 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,26 @@ +# defaults +.history +.vscode/ +/__pycache__ +/.ruff_cache +/cache +/cache.json +/config.json +/extensions/* +/html/extensions.json +/html/themes.json +/metadata.json +/node_modules +/outputs/* +/package-lock.json +/params.txt +/pnpm-lock.yaml +/styles.csv +/tmp +/ui-config.json +/user.css +/venv +/webui-user.bat +/webui-user.sh +/*.log.* +/*.log diff --git a/.gitignore b/.gitignore index dca4e17ad..9e72426c7 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,3 @@ dist/ !/models/VAE-approx/model.pt !/models/Reference !/models/Reference/**/* - diff --git a/CHANGELOG.md b/CHANGELOG.md index 381fe370f..5274d2153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ First, a massive update to docs including new UI top-level **info** tab with acc - [MiaoshouAI PromptGen v2.0](https://huggingface.co/MiaoshouAI/Florence-2-base-PromptGen-v2.0) VQA captioning **Workflow Improvements**: +- Native Docker support - SD3x: ControlNets and all-in-one-safetensors - XYZ grid: benchmarking, video creation, etc. - Enhanced prompt parsing @@ -74,6 +75,7 @@ And quite a few more improvements and fixes since the last update - for full det - *note*: enable *bnb* on-the-fly quantization for even bigger gains - Workflow improvements: + - Native Docker support with pre-defined [Dockerfile](https://github.com/vladmandic/automatic/blob/dev/Dockerfile) - XYZ grid: - optional time benchmark info to individual images - optional add params to individual images diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..e2c689478 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +# SD.Next Dockerfile +FROM pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime +# TBD add org info +LABEL org.opencontainers.image.authors="vladmandic" +WORKDIR / +COPY . . +# stop pip and uv from caching +ENV PIP_NO_CACHE_DIR=true +ENV UV_NO_CACHE=true +# disable model hashing for faster startup +ENV SD_NOHASHING=true +# set data directories +ENV SD_DATADIR="/mnt/data" +ENV SD_MODELSDIR="/mnt/models" +# install dependencies +RUN ["apt-get", "-y", "update"] +RUN ["apt-get", "-y", "install", "git"] +# sdnext will run all necessary pip install ops and then exit +RUN ["python", "launch.py", "--debug", "--uv", "--use-cuda", "--log", "sdnext.log", "--test"] +# preinstall additional packages to avoid installation during runtime +RUN ["uv", "pip", "install", "-r", "requirements-extra.txt"] +# actually run sdnext +CMD ["python", "launch.py", "--debug", "--skip-all", "--listen", "--quick", "--api-log", "--log", "sdnext.log"] +# expose port +EXPOSE 7860 +# TBD add healthcheck function +HEALTHCHECK NONE +STOPSIGNAL SIGINT diff --git a/cli/api-txt2img.js b/cli/api-txt2img.js index 8d0e9f5d1..43e09449b 100755 --- a/cli/api-txt2img.js +++ b/cli/api-txt2img.js @@ -5,7 +5,7 @@ const fs = require('fs'); // eslint-disable-line no-undef const process = require('process'); // eslint-disable-line no-undef -const sd_url = process.env.SDAPI_URL || 'http://127.0.0.1:7860'; +const sd_url = process.env.SDAPI_URL || 'http://127.0.0.1:32769'; const sd_username = process.env.SDAPI_USR; const sd_password = process.env.SDAPI_PWD; const sd_options = { diff --git a/installer.py b/installer.py index 6700f4f19..80bca224c 100644 --- a/installer.py +++ b/installer.py @@ -459,6 +459,8 @@ def check_python(supported_minors=[9, 10, 11, 12], reason=None): # check diffusers version def check_diffusers(): + if args.skip_all or args.skip_requirements: + return sha = 'dac623b59f52c58383a39207d5147aa34e0047cd' pkg = pkg_resources.working_set.by_key.get('diffusers', None) minor = int(pkg.version.split('.')[1] if pkg is not None else 0) @@ -474,6 +476,8 @@ def check_diffusers(): # check onnx version def check_onnx(): + if args.skip_all or args.skip_requirements: + return if not installed('onnx', quiet=True): install('onnx', 'onnx', ignore=True) if not installed('onnxruntime', quiet=True) and not (installed('onnxruntime-gpu', quiet=True) or installed('onnxruntime-openvino', quiet=True) or installed('onnxruntime-training', quiet=True)): # allow either @@ -481,6 +485,8 @@ def check_onnx(): def check_torchao(): + if args.skip_all or args.skip_requirements: + return if installed('torchao', quiet=True): ver = package_version('torchao') if ver != '0.5.0': @@ -492,14 +498,16 @@ def check_torchao(): def install_cuda(): log.info('CUDA: nVidia toolkit detected') - install('onnxruntime-gpu', 'onnxruntime-gpu', ignore=True, quiet=True) + if not (args.skip_all or args.skip_requirements): + install('onnxruntime-gpu', 'onnxruntime-gpu', ignore=True, quiet=True) # return os.environ.get('TORCH_COMMAND', 'torch torchvision --index-url https://download.pytorch.org/whl/cu124') return os.environ.get('TORCH_COMMAND', 'torch==2.5.1+cu124 torchvision==0.20.1+cu124 --index-url https://download.pytorch.org/whl/cu124') def install_rocm_zluda(): + if args.skip_all or args.skip_requirements: + return from modules import rocm - if not rocm.is_installed: log.warning('ROCm: could not find ROCm toolkit installed') log.info('Using CPU-only torch') diff --git a/launch.py b/launch.py index 903234490..af3db2c0f 100755 --- a/launch.py +++ b/launch.py @@ -204,13 +204,13 @@ def main(): installer.check_python() if args.reset: installer.git_reset() - if args.skip_git: + if args.skip_git or args.skip_all: installer.log.info('Skipping GIT operations') installer.check_version() installer.log.info(f'Platform: {installer.print_dict(installer.get_platform())}') installer.check_venv() installer.log.info(f'Args: {sys.argv[1:]}') - if not args.skip_env: + if not args.skip_env or args.skip_all: installer.set_environment() if args.uv: installer.install("uv", "uv") diff --git a/modules/shared.py b/modules/shared.py index 9d56c25d5..c32aa80c0 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -83,6 +83,8 @@ dir_timestamps = {} dir_cache = {} max_workers = 8 +if os.environ.get("SD_HFCACHEDIR", None) is not None: + hfcache_dir = os.environ.get("SD_HFCACHEDIR") if os.environ.get("HF_HUB_CACHE", None) is not None: hfcache_dir = os.environ.get("HF_HUB_CACHE") elif os.environ.get("HF_HUB", None) is not None: