diff --git a/README.md b/README.md index 3348ea0..ae1ce79 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,15 @@ # Stable Diffusion WebUI Podman -Run Stable Diffusion on your Radeon machine with a nice UI without any hassle! +Run Stable Diffusion web browser accessible UI on your CUDA/ROCm machine without any hassle! NOTE: -- Only ROCm supported for now - Supports AUTOMATIC1111 and ComfyUI -- CUDA support to be worked on later +- Supports CUDA and ROCm +- Supports SD 1.5 and SDXL for AUTOMATIC1111 and ComfyUI +- Supports SD 3 for ComfyUI - Requires podman-compose 1.1.0 or newer -## Setup & Usage - -> Note: In progress +## Quick Setup **Download necessary models** ``` @@ -18,15 +17,35 @@ $ podman-compose --profile download build $ podman-compose --profile download up -d ``` -**Run AUTOMATIC1111 Stable Diffusion Web UI** +**Run AUTOMATIC1111 Stable Diffusion Web UI with CUDA support** ``` -$ podman-compose --profile auto build -$ podman-compose --profile auto up -d +$ podman-compose --profile auto-cuda build +$ podman-compose --profile auto-cuda up -d ``` +**You can change `--profile auto-cuda` to different profile:** + +| Profile | Description | +|--------------|---------------------------------| +| auto-cuda | AUTOMATIC1111 with CUDA support | +| auto-rocm | AUTOMATIC1111 with ROCm support | +| comfyui-cuda | ComfyUI with CUDA support | +| comfyui-rocm | ComfyUI with ROCm support | + +## Set the container as systemd service to allow running on user login + **Create AUTOMATIC1111 Stable Diffusion Web UI Podman service** + +Find the name of the running container + ``` -$ podman generate systemd --new webui-docker_auto_1 > ~/.config/systemd/user/automatic1111.service +$ podman ps +``` + +Set the container as systemd service. E.g. for container named `webui-podman_auto_1`: + +``` +$ podman generate systemd --new webui-podman_auto_1 > ~/.config/systemd/user/automatic1111.service ``` **Enable and run AUTOMATIC1111 Stable Diffusion Web UI Podman service** @@ -34,7 +53,20 @@ $ podman generate systemd --new webui-docker_auto_1 > ~/.config/systemd/user/aut $ systemctl --user enable --now automatic1111.service ``` -**You can change `--profile auto` to `--profile comfy` to change AUTOMATIC1111 to ComfyUI** +## Stable Diffusion 3 + +**Download models here:** +[Stable Diffusion 3 on HuggingFace](https://huggingface.co/stabilityai/stable-diffusion-3-medium) + +**Put SD3 models here:** +``` +/data/models/Stable-diffusion +``` + +**Put SD3 text encoders here:** +``` +/data/models/CLIPEncoder +``` ## Features @@ -48,14 +80,6 @@ This repository provides multiple UIs for you to play around with stable diffusi | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | ![](https://user-images.githubusercontent.com/24505302/189541954-46afd772-d0c8-4005-874c-e2eca40c02f2.jpg) | ![](https://user-images.githubusercontent.com/24505302/189541956-5b528de7-1b5d-479f-a1db-d3f5a53afc59.jpg) | ![](https://user-images.githubusercontent.com/24505302/189541957-cf78b352-a071-486d-8889-f26952779a61.jpg) | -### [InvokeAI](https://github.com/invoke-ai/InvokeAI) - -[Full feature list here](https://github.com/invoke-ai/InvokeAI#features), Screenshots: - -| Text to image | Image to image | Extras | -| ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -| ![](https://user-images.githubusercontent.com/24505302/195158552-39f58cb6-cfcc-4141-9995-a626e3760752.jpg) | ![](https://user-images.githubusercontent.com/24505302/195158553-152a0ab8-c0fd-4087-b121-4823bcd8d6b5.jpg) | ![](https://user-images.githubusercontent.com/24505302/195158548-e118206e-c519-4915-85d6-4c248eb10fc0.jpg) | - ### [ComfyUI](https://github.com/comfyanonymous/ComfyUI) [Full feature list here](https://github.com/comfyanonymous/ComfyUI#features), Screenshot: diff --git a/data/.gitignore b/data/.gitignore index 946349a..12b376c 100644 --- a/data/.gitignore +++ b/data/.gitignore @@ -1,4 +1,6 @@ /.cache -/config +/config/auto +/config/comfy/custom_nodes +/config/comfy/input /embeddings /models diff --git a/data/config/comfy/my_workflows/comfy_example_workflows_sd3_medium_example_workflow_basic.json b/data/config/comfy/my_workflows/comfy_example_workflows_sd3_medium_example_workflow_basic.json new file mode 100644 index 0000000..c3515ad --- /dev/null +++ b/data/config/comfy/my_workflows/comfy_example_workflows_sd3_medium_example_workflow_basic.json @@ -0,0 +1 @@ +{"last_node_id":272,"last_link_id":599,"nodes":[{"id":11,"type":"TripleCLIPLoader","pos":[-1885,-49],"size":{"0":315,"1":106},"flags":{},"order":0,"mode":0,"outputs":[{"name":"CLIP","type":"CLIP","links":[5,94],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"TripleCLIPLoader"},"widgets_values":["clip_g.safetensors","clip_l.safetensors","t5xxl_fp8_e4m3fn.safetensors"]},{"id":71,"type":"CLIPTextEncode","pos":[-1869.2871546875003,560.071803930664],"size":{"0":380.4615783691406,"1":102.07693481445312},"flags":{},"order":6,"mode":0,"inputs":[{"name":"clip","type":"CLIP","link":94}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[93,580],"shape":3,"slot_index":0}],"title":"CLIP Text Encode (Negative Prompt)","properties":{"Node name for S&R":"CLIPTextEncode"},"widgets_values":["bad quality, poor quality, doll, disfigured, jpg, toy, bad anatomy, missing limbs, missing fingers, 3d, cgi"],"color":"#322","bgcolor":"#533"},{"id":68,"type":"ConditioningSetTimestepRange","pos":[-1010,167],"size":{"0":317.4000244140625,"1":82},"flags":{},"order":10,"mode":0,"inputs":[{"name":"conditioning","type":"CONDITIONING","link":90}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[91],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"ConditioningSetTimestepRange"},"widgets_values":[0.1,1]},{"id":70,"type":"ConditioningSetTimestepRange","pos":[-1006,314],"size":{"0":317.4000244140625,"1":82},"flags":{},"order":8,"mode":0,"inputs":[{"name":"conditioning","type":"CONDITIONING","link":93,"slot_index":0}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[92],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"ConditioningSetTimestepRange"},"widgets_values":[0,0.1]},{"id":67,"type":"ConditioningZeroOut","pos":[-1370,337],"size":{"0":211.60000610351562,"1":26},"flags":{},"order":9,"mode":0,"inputs":[{"name":"conditioning","type":"CONDITIONING","link":580}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[90],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"ConditioningZeroOut"}},{"id":266,"type":"Note","pos":[-2352,576],"size":{"0":308.061279296875,"1":102.86902618408203},"flags":{},"order":1,"mode":0,"properties":{"text":""},"widgets_values":["Resolution should be around 1 megapixel and width/height must be multiple of 64"],"color":"#432","bgcolor":"#653"},{"id":13,"type":"ModelSamplingSD3","pos":[-974,-220],"size":{"0":315,"1":58},"flags":{"collapsed":false},"order":7,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":565}],"outputs":[{"name":"MODEL","type":"MODEL","links":[591],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"ModelSamplingSD3"},"widgets_values":[3]},{"id":69,"type":"ConditioningCombine","pos":[-662,165],"size":{"0":228.39999389648438,"1":46},"flags":{},"order":11,"mode":0,"inputs":[{"name":"conditioning_1","type":"CONDITIONING","link":91},{"name":"conditioning_2","type":"CONDITIONING","link":92}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[592],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"ConditioningCombine"}},{"id":233,"type":"PreviewImage","pos":[535.1143750722272,-147.92548481673106],"size":{"0":604.7489624023438,"1":592.15576171875},"flags":{},"order":14,"mode":0,"inputs":[{"name":"images","type":"IMAGE","link":599}],"properties":{"Node name for S&R":"PreviewImage"}},{"id":231,"type":"VAEDecode","pos":[141,-177],"size":{"0":210,"1":46},"flags":{},"order":13,"mode":0,"inputs":[{"name":"samples","type":"LATENT","link":596},{"name":"vae","type":"VAE","link":557}],"outputs":[{"name":"IMAGE","type":"IMAGE","links":[599],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"VAEDecode"}},{"id":252,"type":"CheckpointLoaderSimple","pos":[-2314,-203],"size":{"0":746.7357788085938,"1":98},"flags":{},"order":2,"mode":0,"outputs":[{"name":"MODEL","type":"MODEL","links":[565],"shape":3,"slot_index":0},{"name":"CLIP","type":"CLIP","links":[],"shape":3,"slot_index":1},{"name":"VAE","type":"VAE","links":[557],"shape":3,"slot_index":2}],"properties":{"Node name for S&R":"CheckpointLoaderSimple"},"widgets_values":["sdv3/2b_1024/sd3_medium.safetensors"]},{"id":271,"type":"KSampler","pos":[-269,-179],"size":{"0":315,"1":446},"flags":{},"order":12,"mode":0,"inputs":[{"name":"model","type":"MODEL","link":591},{"name":"positive","type":"CONDITIONING","link":595},{"name":"negative","type":"CONDITIONING","link":592},{"name":"latent_image","type":"LATENT","link":593},{"name":"seed","type":"INT","link":597,"widget":{"name":"seed"},"slot_index":4}],"outputs":[{"name":"LATENT","type":"LATENT","links":[596],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"KSampler"},"widgets_values":[945512652412924,"fixed",28,4.5,"dpmpp_2m","sgm_uniform",1]},{"id":135,"type":"EmptySD3LatentImage","pos":[-2352,438],"size":{"0":315,"1":106},"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"name":"LATENT","type":"LATENT","links":[593],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"EmptySD3LatentImage"},"widgets_values":[1024,1024,1]},{"id":6,"type":"CLIPTextEncode","pos":[-1876.2871546875003,284.0718039306641],"size":{"0":389.06927490234375,"1":207.84902954101562},"flags":{},"order":5,"mode":0,"inputs":[{"name":"clip","type":"CLIP","link":5}],"outputs":[{"name":"CONDITIONING","type":"CONDITIONING","links":[595],"shape":3,"slot_index":0}],"properties":{"Node name for S&R":"CLIPTextEncode"},"widgets_values":["a female character with long, flowing hair that appears to be made of ethereal, swirling patterns resembling the Northern Lights or Aurora Borealis. The background is dominated by deep blues and purples, creating a mysterious and dramatic atmosphere. The character's face is serene, with pale skin and striking features. She wears a dark-colored outfit with subtle patterns. The overall style of the artwork is reminiscent of fantasy or supernatural genres"],"color":"#232","bgcolor":"#353"},{"id":272,"type":"PrimitiveNode","pos":[-2342,278],"size":{"0":210,"1":82},"flags":{},"order":4,"mode":0,"outputs":[{"name":"INT","type":"INT","links":[597],"slot_index":0,"widget":{"name":"seed"}}],"title":"Seed","properties":{"Run widget replace on values":false},"widgets_values":[945512652412924,"fixed"]}],"links":[[5,11,0,6,0,"CLIP"],[90,67,0,68,0,"CONDITIONING"],[91,68,0,69,0,"CONDITIONING"],[92,70,0,69,1,"CONDITIONING"],[93,71,0,70,0,"CONDITIONING"],[94,11,0,71,0,"CLIP"],[557,252,2,231,1,"VAE"],[565,252,0,13,0,"MODEL"],[580,71,0,67,0,"CONDITIONING"],[591,13,0,271,0,"MODEL"],[592,69,0,271,2,"CONDITIONING"],[593,135,0,271,3,"LATENT"],[595,6,0,271,1,"CONDITIONING"],[596,271,0,231,0,"LATENT"],[597,272,0,271,4,"INT"],[599,231,0,233,0,"IMAGE"]],"groups":[{"title":"Load Models","bounding":[-2410,-339,969,488],"color":"#3f789e","font_size":24},{"title":"Input","bounding":[-2409,181,972,523],"color":"#3f789e","font_size":24},{"title":"Output","bounding":[464,-273,741,814],"color":"#3f789e","font_size":24}],"config":{},"extra":{"workspace_info":{"id":"c99xeQ-KV6bMlRCuIsCIC"}},"version":0.4} \ No newline at end of file diff --git a/data/config/comfy/my_workflows/workflow_comfy_sd3.json b/data/config/comfy/my_workflows/workflow_comfy_sd3.json new file mode 100644 index 0000000..d9b7ff5 --- /dev/null +++ b/data/config/comfy/my_workflows/workflow_comfy_sd3.json @@ -0,0 +1,971 @@ +{ + "last_node_id": 277, + "last_link_id": 609, + "nodes": [ + { + "id": 231, + "type": "VAEDecode", + "pos": [ + -326, + -221 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 596 + }, + { + "name": "vae", + "type": "VAE", + "link": 557 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 601, + 608 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 276, + "type": "SaveImage", + "pos": [ + -323, + -119 + ], + "size": { + "0": 497.3695068359375, + "1": 563.1148071289062 + }, + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 608 + } + ], + "properties": {}, + "widgets_values": [ + "1089" + ] + }, + { + "id": 275, + "type": "UpscaleModelLoader", + "pos": [ + 210, + -240 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "UPSCALE_MODEL", + "type": "UPSCALE_MODEL", + "links": [ + 606 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "UpscaleModelLoader" + }, + "widgets_values": [ + "4x-UltraSharp.pth" + ] + }, + { + "id": 274, + "type": "UltimateSDUpscale", + "pos": [ + 210, + -100 + ], + "size": { + "0": 308.3812561035156, + "1": 619.0059204101562 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 601 + }, + { + "name": "model", + "type": "MODEL", + "link": 602 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 603 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 604 + }, + { + "name": "vae", + "type": "VAE", + "link": 605 + }, + { + "name": "upscale_model", + "type": "UPSCALE_MODEL", + "link": 606, + "slot_index": 5 + }, + { + "name": "seed", + "type": "INT", + "link": 607, + "widget": { + "name": "seed" + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 609 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "UltimateSDUpscale" + }, + "widgets_values": [ + 2, + 521116954032249, + "randomize", + 15, + 5, + "dpmpp_2m", + "sgm_uniform", + 0.15, + "Chess", + 1024, + 1024, + 8, + 32, + "None", + 1, + 64, + 8, + 16, + true, + false + ] + }, + { + "id": 252, + "type": "CheckpointLoaderSimple", + "pos": [ + -1732.086240502146, + -431.1332989178405 + ], + "size": { + "0": 499.92315673828125, + "1": 98 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 565 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [], + "shape": 3, + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 557, + 605 + ], + "shape": 3, + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "sd3m/sd3_medium.safetensors" + ] + }, + { + "id": 13, + "type": "ModelSamplingSD3", + "pos": [ + -1189, + -420 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": { + "collapsed": false + }, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 565 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 591, + 602 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ModelSamplingSD3" + }, + "widgets_values": [ + 3 + ] + }, + { + "id": 277, + "type": "SaveImage", + "pos": [ + 547, + -100 + ], + "size": { + "0": 528.3096923828125, + "1": 612.62255859375 + }, + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 609 + } + ], + "properties": {}, + "widgets_values": [ + "1089" + ] + }, + { + "id": 272, + "type": "PrimitiveNode", + "pos": [ + -1270, + 610 + ], + "size": { + "0": 210, + "1": 80 + }, + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 597, + 607 + ], + "slot_index": 0, + "widget": { + "name": "seed" + } + } + ], + "title": "Seed", + "properties": { + "Run widget replace on values": false + }, + "widgets_values": [ + 521116954032249, + "randomize" + ] + }, + { + "id": 135, + "type": "EmptySD3LatentImage", + "pos": [ + -1270, + 420 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 593 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "EmptySD3LatentImage" + }, + "widgets_values": [ + 1024, + 1024, + 1 + ] + }, + { + "id": 266, + "type": "Note", + "pos": [ + -1569, + 424 + ], + "size": { + "0": 270.8642578125, + "1": 97.72545623779297 + }, + "flags": {}, + "order": 4, + "mode": 0, + "properties": { + "text": "" + }, + "widgets_values": [ + "The resolution should be around 1 megapixel (1 million pixels), with both the width and height being multiples of 64. For example, an image with a resolution of 1024 x 1024 pixels is approximately 1 megapixel." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 67, + "type": "ConditioningZeroOut", + "pos": [ + -1250, + -50 + ], + "size": { + "0": 245.96969604492188, + "1": 31.455402374267578 + }, + "flags": { + "collapsed": false + }, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 580 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 90 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ConditioningZeroOut" + } + }, + { + "id": 68, + "type": "ConditioningSetTimestepRange", + "pos": [ + -1250, + 50 + ], + "size": { + "0": 242.7754669189453, + "1": 82.08560943603516 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 90 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 91 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ConditioningSetTimestepRange" + }, + "widgets_values": [ + 0.1, + 1 + ] + }, + { + "id": 70, + "type": "ConditioningSetTimestepRange", + "pos": [ + -1270, + 200 + ], + "size": { + "0": 266.7044677734375, + "1": 82 + }, + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 93, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 92 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ConditioningSetTimestepRange" + }, + "widgets_values": [ + 0, + 0.1 + ] + }, + { + "id": 71, + "type": "CLIPTextEncode", + "pos": [ + -1720, + 220 + ], + "size": { + "0": 380.4615783691406, + "1": 102.07693481445312 + }, + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 94 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 93, + 580, + 604 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "CLIP Text Encode (Negative Prompt)", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "bad quality, poor quality" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 6, + "type": "CLIPTextEncode", + "pos": [ + -1709, + -49 + ], + "size": { + "0": 374.9269714355469, + "1": 196.8705291748047 + }, + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 5 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 595, + 603 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Three same-size adorable and cute animals in coats outdoors in a picturesque and beautiful summer setting: a Golden Retriever in a cozy red coat, a Siamese cat in a snug blue solid-colored coat, and a fluffy rabbit in a yellow fur-trimmed coat. ((One of the animals holds an ad board with \"SD3\" correctly written in very big and bold letters.)), the background is a vibrant garden filled with blooming flowers, lush green grass, and a clear blue sky. " + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 69, + "type": "ConditioningCombine", + "pos": [ + -976, + 112 + ], + "size": { + "0": 228.39999389648438, + "1": 46 + }, + "flags": { + "collapsed": false + }, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "conditioning_1", + "type": "CONDITIONING", + "link": 91 + }, + { + "name": "conditioning_2", + "type": "CONDITIONING", + "link": 92 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 592 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ConditioningCombine" + } + }, + { + "id": 271, + "type": "KSampler", + "pos": [ + -695, + -221 + ], + "size": { + "0": 328.7803649902344, + "1": 651.587890625 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 591 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 595 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 592 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 593 + }, + { + "name": "seed", + "type": "INT", + "link": 597, + "widget": { + "name": "seed" + }, + "slot_index": 4 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 596 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 521116954032249, + "fixed", + 28, + 5, + "dpmpp_2m", + "sgm_uniform", + 1 + ] + }, + { + "id": 11, + "type": "TripleCLIPLoader", + "pos": [ + -1525, + -360 + ], + "size": { + "0": 502.6791076660156, + "1": 106 + }, + "flags": {}, + "order": 5, + "mode": 0, + "outputs": [ + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 5, + 94 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "TripleCLIPLoader" + }, + "widgets_values": [ + "sd3m/clip_g.safetensors", + "sd3m/clip_l.safetensors", + "sd3m/t5xxl_fp8_e4m3fn.safetensors" + ] + } + ], + "links": [ + [ + 5, + 11, + 0, + 6, + 0, + "CLIP" + ], + [ + 90, + 67, + 0, + 68, + 0, + "CONDITIONING" + ], + [ + 91, + 68, + 0, + 69, + 0, + "CONDITIONING" + ], + [ + 92, + 70, + 0, + 69, + 1, + "CONDITIONING" + ], + [ + 93, + 71, + 0, + 70, + 0, + "CONDITIONING" + ], + [ + 94, + 11, + 0, + 71, + 0, + "CLIP" + ], + [ + 557, + 252, + 2, + 231, + 1, + "VAE" + ], + [ + 565, + 252, + 0, + 13, + 0, + "MODEL" + ], + [ + 580, + 71, + 0, + 67, + 0, + "CONDITIONING" + ], + [ + 591, + 13, + 0, + 271, + 0, + "MODEL" + ], + [ + 592, + 69, + 0, + 271, + 2, + "CONDITIONING" + ], + [ + 593, + 135, + 0, + 271, + 3, + "LATENT" + ], + [ + 595, + 6, + 0, + 271, + 1, + "CONDITIONING" + ], + [ + 596, + 271, + 0, + 231, + 0, + "LATENT" + ], + [ + 597, + 272, + 0, + 271, + 4, + "INT" + ], + [ + 601, + 231, + 0, + 274, + 0, + "IMAGE" + ], + [ + 602, + 13, + 0, + 274, + 1, + "MODEL" + ], + [ + 603, + 6, + 0, + 274, + 2, + "CONDITIONING" + ], + [ + 604, + 71, + 0, + 274, + 3, + "CONDITIONING" + ], + [ + 605, + 252, + 2, + 274, + 4, + "VAE" + ], + [ + 606, + 275, + 0, + 274, + 5, + "UPSCALE_MODEL" + ], + [ + 607, + 272, + 0, + 274, + 6, + "INT" + ], + [ + 608, + 231, + 0, + 276, + 0, + "IMAGE" + ], + [ + 609, + 274, + 0, + 277, + 0, + "IMAGE" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 0.8264462809917354, + "offset": { + "0": 1520.1177791634934, + "1": 475.14227251761054 + } + }, + "workspace_info": { + "id": "0d10c5f4-4d08-4f60-82ee-f30e9f4292f3" + } + }, + "version": 0.4 +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index ba2d609..c281a61 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,32 +8,10 @@ x-base_service: &base_service - &v2 ./output:/output:Z security_opt: - label=disable - devices: - - /dev/dri - - /dev/kfd ipc: - host - # ulimit: - # - host - # cgroupns: - # - host - # volumes: - # - &v1 ./data:/data - # - &v2 ./output:/output - # stop_signal: SIGKILL - # tty: true - # security_opt: - # - label=type:nvidia_container_t - # deploy: - # resources: - # reservations: - # devices: - # - /dev/dri:/dev/kfd - # - driver: nvidia - # device_ids: ['0'] - # capabilities: [compute, utility] -name: webui-docker +name: webui-podman services: download: @@ -42,11 +20,25 @@ services: volumes: - *v1 - auto: &automatic + auto-cuda: &automatic-cuda <<: *base_service - profiles: ["auto"] - build: ./services/AUTOMATIC1111 - image: sd-auto:72 + profiles: ["auto-cuda"] + build: ./services/AUTOMATIC1111-cuda + image: sd-auto:193 + devices: + - nvidia.com/gpu=all + environment: + # - CLI_ARGS=--allow-code --medvram --xformers --enable-insecure-extension-access --api + - CLI_ARGS=--allow-code --enable-insecure-extension-access --api + + auto-rocm: &automatic-rocm + <<: *base_service + profiles: ["auto-rocm"] + build: ./services/AUTOMATIC1111-rocm + image: sd-auto:193 + devices: + - /dev/dri + - /dev/kfd environment: # - CLI_ARGS=--allow-code --medvram --xformers --enable-insecure-extension-access --api - CLI_ARGS=--allow-code --enable-insecure-extension-access --api @@ -76,13 +68,27 @@ services: # - PRELOAD=true # - CLI_ARGS=--always_use_cpu - comfy: &comfy + comfy-cuda: &comfy-cuda <<: *base_service - profiles: ["comfy"] - build: ./services/comfy/ - image: sd-comfy:6 + profiles: ["comfy-cuda"] + build: ./services/comfy-cuda/ + image: sd-comfy:5eb98f00927ace00b6b3d01ed9c76b113fc4ec9f + devices: + - nvidia.com/gpu=all environment: - CLI_ARGS= + + comfy-rocm: &comfy-rocm + <<: *base_service + profiles: ["comfy-rocm"] + build: ./services/comfy-rocm/ + image: sd-comfy:5eb98f00927ace00b6b3d01ed9c76b113fc4ec9f + devices: + - /dev/dri + - /dev/kfd + environment: + - CLI_ARGS= + # # # comfy-cpu: diff --git a/selinux-cache.sh b/selinux-cache.sh index 6099f64..c412ad2 100755 --- a/selinux-cache.sh +++ b/selinux-cache.sh @@ -6,6 +6,9 @@ # "Z" will force all files to be accessable by the current build step, fixing # the "file not found" issue. +# WARNING: DON'T RUN THIS FOR NOW! +# TODO: INTEGRATE THIS SCRIPT SOMEHOW FOR DOCKER COMPATIBILITY + disabled_pip="/root/.cache/pip " enabled_pip="/root/.cache/pip,Z " disabled_apt="/var/cache/apt " diff --git a/services/AUTOMATIC1111-cuda/Dockerfile b/services/AUTOMATIC1111-cuda/Dockerfile new file mode 100644 index 0000000..d9808ce --- /dev/null +++ b/services/AUTOMATIC1111-cuda/Dockerfile @@ -0,0 +1,76 @@ +FROM alpine/git:2.36.2 as download + +COPY clone.sh /clone.sh + + +RUN . /clone.sh stable-diffusion-stability-ai https://github.com/Stability-AI/stablediffusion.git cf1d67a6fd5ea1aa600c4df58e5b47da45f6bdbf \ + && rm -rf assets data/**/*.png data/**/*.jpg data/**/*.gif + +RUN . /clone.sh CodeFormer https://github.com/sczhou/CodeFormer.git c5b4593074ba6214284d6acd5f1719b6c5d739af \ + && rm -rf assets inputs + +RUN . /clone.sh BLIP https://github.com/salesforce/BLIP.git 48211a1594f1321b00f14c9f7a5b4813144b2fb9 +RUN . /clone.sh k-diffusion https://github.com/crowsonkb/k-diffusion.git ab527a9a6d347f364e3d185ba6d714e22d80cb3c +RUN . /clone.sh clip-interrogator https://github.com/pharmapsychotic/clip-interrogator 2cf03aaf6e704197fd0dae7c7f96aa59cf1b11c9 +RUN . /clone.sh generative-models https://github.com/Stability-AI/generative-models 45c443b316737a4ab6e40413d7794a7f5657c19f + + +FROM pytorch/pytorch:2.1.2-cuda12.1-cudnn8-runtime + +ENV DEBIAN_FRONTEND=noninteractive PIP_PREFER_BINARY=1 + +RUN --mount=type=cache,target=/var/cache/apt,Z \ + apt-get update && \ + # we need those + apt-get install -y fonts-dejavu-core rsync git jq moreutils aria2 cargo\ + # extensions needs those + ffmpeg libglfw3-dev libgles2-mesa-dev pkg-config libcairo2 libcairo2-dev build-essential + + +WORKDIR / +RUN --mount=type=cache,target=/root/.cache/pip,Z \ + git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git && \ + cd stable-diffusion-webui && \ + git checkout tags/v1.9.3 && \ + pip install --upgrade pip && \ + pip install -r requirements.txt && \ + pip install pytorch_lightning==1.7.7 torchmetrics==0.11.4 pydantic==1.10.11 && \ + mkdir repositories && cd repositories && \ + git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui-assets.git + +ENV ROOT=/stable-diffusion-webui + +COPY --from=download /repositories/ ${ROOT}/repositories/ +RUN mkdir ${ROOT}/interrogate && cp ${ROOT}/repositories/clip-interrogator/clip_interrogator/data/* ${ROOT}/interrogate +RUN --mount=type=cache,target=/root/.cache/pip,Z \ + pip install -r ${ROOT}/repositories/CodeFormer/requirements.txt + +RUN --mount=type=cache,target=/root/.cache/pip,Z \ + # pip install pyngrok xformers==0.0.23.post1 \ + pip install pyngrok \ + git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379 \ + git+https://github.com/openai/CLIP.git@d50d76daa670286dd6cacf3bcd80b5e4823fc8e1 \ + git+https://github.com/mlfoundations/open_clip.git@v2.20.0 + +# there seems to be a memory leak (or maybe just memory not being freed fast enough) that is fixed by this version of malloc +# maybe move this up to the dependencies list. +RUN apt-get -y install libgoogle-perftools-dev && apt-get clean +ENV LD_PRELOAD=libtcmalloc.so + +COPY . /docker + +RUN \ + # mv ${ROOT}/style.css ${ROOT}/user.css && \ + # one of the ugliest hacks I ever wrote \ +# ls /opt/conda/lib/python3.12/site-packages && \ +# which python3 && \ +# pip show gradio && \ + sed -i 's/in_app_dir = .*/in_app_dir = True/g' /opt/conda/envs/py_3.10/lib/python3.10/site-packages/gradio/routes.py && \ + git config --global --add safe.directory '*' + +WORKDIR ${ROOT} +# ENV NVIDIA_VISIBLE_DEVICES=all +ENV CLI_ARGS="" +EXPOSE 7860 +ENTRYPOINT ["/docker/entrypoint.sh"] +CMD python -u webui.py --listen --port 7860 ${CLI_ARGS} diff --git a/services/AUTOMATIC1111/clone.sh b/services/AUTOMATIC1111-cuda/clone.sh similarity index 100% rename from services/AUTOMATIC1111/clone.sh rename to services/AUTOMATIC1111-cuda/clone.sh diff --git a/services/AUTOMATIC1111/config.py b/services/AUTOMATIC1111-cuda/config.py similarity index 100% rename from services/AUTOMATIC1111/config.py rename to services/AUTOMATIC1111-cuda/config.py diff --git a/services/AUTOMATIC1111/entrypoint.sh b/services/AUTOMATIC1111-cuda/entrypoint.sh similarity index 100% rename from services/AUTOMATIC1111/entrypoint.sh rename to services/AUTOMATIC1111-cuda/entrypoint.sh diff --git a/services/AUTOMATIC1111/Dockerfile b/services/AUTOMATIC1111-rocm/Dockerfile similarity index 96% rename from services/AUTOMATIC1111/Dockerfile rename to services/AUTOMATIC1111-rocm/Dockerfile index eab3a41..dc9131f 100644 --- a/services/AUTOMATIC1111/Dockerfile +++ b/services/AUTOMATIC1111-rocm/Dockerfile @@ -15,7 +15,6 @@ RUN . /clone.sh clip-interrogator https://github.com/pharmapsychotic/clip-interr RUN . /clone.sh generative-models https://github.com/Stability-AI/generative-models 45c443b316737a4ab6e40413d7794a7f5657c19f -# FROM pytorch/pytorch:2.1.2-cuda12.1-cudnn8-runtime FROM rocm/pytorch:rocm6.1_ubuntu22.04_py3.10_pytorch_2.1.2 ENV DEBIAN_FRONTEND=noninteractive PIP_PREFER_BINARY=1 @@ -32,7 +31,6 @@ WORKDIR / RUN --mount=type=cache,target=/root/.cache/pip,Z \ git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git && \ cd stable-diffusion-webui && \ -# git reset --hard cf2772fab0af5573da775e7437e6acdca424f26e && \ git checkout tags/v1.9.3 && \ pip install --upgrade pip && \ pip install -r requirements.txt && \ diff --git a/services/AUTOMATIC1111-rocm/clone.sh b/services/AUTOMATIC1111-rocm/clone.sh new file mode 100644 index 0000000..cfdf0a2 --- /dev/null +++ b/services/AUTOMATIC1111-rocm/clone.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -Eeuox pipefail + +mkdir -p /repositories/"$1" +cd /repositories/"$1" +git init +git remote add origin "$2" +git fetch origin "$3" --depth=1 +git reset --hard "$3" +rm -rf .git diff --git a/services/AUTOMATIC1111-rocm/config.py b/services/AUTOMATIC1111-rocm/config.py new file mode 100644 index 0000000..b8d699e --- /dev/null +++ b/services/AUTOMATIC1111-rocm/config.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 + +"""Checks and sets default values for config.json before starting the container.""" + +import json +import re +import os.path +import sys + +DEFAULT_FILEPATH = '/data/config/auto/config.json' + +DEFAULT_OUTDIRS = { + "outdir_samples": "", + "outdir_txt2img_samples": "/output/txt2img", + "outdir_img2img_samples": "/output/img2img", + "outdir_extras_samples": "/output/extras", + "outdir_grids": "", + "outdir_txt2img_grids": "/output/txt2img-grids", + "outdir_img2img_grids": "/output/img2img-grids", + "outdir_save": "/output/saved", + "outdir_init_images": "/output/init-images", +} +RE_VALID_OUTDIR = re.compile(r"(^/output(/\.?[\w\-\_]+)+/?$)|(^\s?$)") + +DEFAULT_OTHER = { + "font": "DejaVuSans.ttf", +} + +def dict_to_json_file(target_file: str, data: dict): + """Write dictionary to specified json file""" + + with open(target_file, 'w') as f: + json.dump(data, f) + +def json_file_to_dict(config_file: str) -> dict|None: + """Load json file into a dictionary. Return None if file does not exist.""" + + if os.path.isfile(config_file): + with open(config_file, 'r') as f: + return json.load(f) + else: + return None + +def replace_if_invalid(value: str, replacement: str, pattern: str|re.Pattern[str]) -> str: + """Returns original value if valid, fallback value if invalid""" + + if re.match(pattern, value): + return value + else: + return replacement + +def check_and_replace_config(config_file: str, target_file: str = None): + """Checks given file for invalid values. Replaces those with fallback values (default: overwrites file).""" + + # Get current user config, or empty if file does not exists + data = json_file_to_dict(config_file) or {} + + # Check and fix output directories + for k, def_val in DEFAULT_OUTDIRS.items(): + if k not in data: + data[k] = def_val + else: + data[k] = replace_if_invalid(value=data[k], replacement=def_val, pattern=RE_VALID_OUTDIR) + + # Check and fix other default settings + for k, def_val in DEFAULT_OTHER.items(): + if k not in data: + data[k] = def_val + + # Write results to file + dict_to_json_file(target_file or config_file, data) + +if __name__ == '__main__': + if len(sys.argv) > 1: + check_and_replace_config(*sys.argv[1:]) + else: + check_and_replace_config(DEFAULT_FILEPATH) + diff --git a/services/AUTOMATIC1111-rocm/entrypoint.sh b/services/AUTOMATIC1111-rocm/entrypoint.sh new file mode 100755 index 0000000..35023af --- /dev/null +++ b/services/AUTOMATIC1111-rocm/entrypoint.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +set -Eeuo pipefail + +# TODO: move all mkdir -p ? +mkdir -p /data/config/auto/scripts/ +# mount scripts individually + +echo $ROOT +ls -lha $ROOT + +find "${ROOT}/scripts/" -maxdepth 1 -type l -delete +cp -vrfTs /data/config/auto/scripts/ "${ROOT}/scripts/" + +# Set up config file +python /docker/config.py /data/config/auto/config.json + +if [ ! -f /data/config/auto/ui-config.json ]; then + echo '{}' >/data/config/auto/ui-config.json +fi + +if [ ! -f /data/config/auto/styles.csv ]; then + touch /data/config/auto/styles.csv +fi + +# copy models from original models folder +mkdir -p /data/models/VAE-approx/ /data/models/karlo/ + +rsync -a --info=NAME ${ROOT}/models/VAE-approx/ /data/models/VAE-approx/ +rsync -a --info=NAME ${ROOT}/models/karlo/ /data/models/karlo/ + +declare -A MOUNTS + +MOUNTS["/root/.cache"]="/data/.cache" +MOUNTS["${ROOT}/models"]="/data/models" + +MOUNTS["${ROOT}/embeddings"]="/data/embeddings" +MOUNTS["${ROOT}/config.json"]="/data/config/auto/config.json" +MOUNTS["${ROOT}/ui-config.json"]="/data/config/auto/ui-config.json" +MOUNTS["${ROOT}/styles.csv"]="/data/config/auto/styles.csv" +MOUNTS["${ROOT}/extensions"]="/data/config/auto/extensions" +MOUNTS["${ROOT}/config_states"]="/data/config/auto/config_states" + +# extra hacks +MOUNTS["${ROOT}/repositories/CodeFormer/weights/facelib"]="/data/.cache" + +for to_path in "${!MOUNTS[@]}"; do + set -Eeuo pipefail + from_path="${MOUNTS[${to_path}]}" + rm -rf "${to_path}" + if [ ! -f "$from_path" ]; then + mkdir -vp "$from_path" + fi + mkdir -vp "$(dirname "${to_path}")" + ln -sT "${from_path}" "${to_path}" + echo Mounted $(basename "${from_path}") +done + +echo "Installing extension dependencies (if any)" + +# because we build our container as root: +chown -R root ~/.cache/ +chmod 766 ~/.cache/ + +shopt -s nullglob +# For install.py, please refer to https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Developing-extensions#installpy +list=(./extensions/*/install.py) +for installscript in "${list[@]}"; do + EXTNAME=$(echo $installscript | cut -d '/' -f 3) + # Skip installing dependencies if extension is disabled in config + if $(jq -e ".disabled_extensions|any(. == \"$EXTNAME\")" config.json); then + echo "Skipping disabled extension ($EXTNAME)" + continue + fi + PYTHONPATH=${ROOT} python "$installscript" +done + +if [ -f "/data/config/auto/startup.sh" ]; then + pushd ${ROOT} + echo "Running startup script" + . /data/config/auto/startup.sh + popd +fi + +exec "$@" diff --git a/services/comfy-cuda/Dockerfile b/services/comfy-cuda/Dockerfile new file mode 100644 index 0000000..5d6029a --- /dev/null +++ b/services/comfy-cuda/Dockerfile @@ -0,0 +1,23 @@ +FROM pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime + +ENV DEBIAN_FRONTEND=noninteractive PIP_PREFER_BINARY=1 + +RUN apt-get update && apt-get install -y git cargo nasm && apt-get clean + +ENV ROOT=/stable-diffusion +RUN --mount=type=cache,target=/root/.cache/pip,Z \ + git clone --recursive https://github.com/comfyanonymous/ComfyUI.git ${ROOT} && \ + cd ${ROOT} && \ + git checkout master && \ + git reset --hard 5eb98f00927ace00b6b3d01ed9c76b113fc4ec9f && \ + pip install -r requirements.txt + +WORKDIR ${ROOT} +COPY . /docker/ +RUN chmod u+x /docker/entrypoint.sh && cp /docker/extra_model_paths.yaml ${ROOT} + +ENV NVIDIA_VISIBLE_DEVICES=all PYTHONPATH="${PYTHONPATH}:${PWD}" CLI_ARGS="" +ENV PYTHONPATH="${PYTHONPATH}:${PWD}" CLI_ARGS="" +EXPOSE 7860 +ENTRYPOINT ["/docker/entrypoint.sh"] +CMD python -u main.py --listen --port 7860 ${CLI_ARGS} diff --git a/services/comfy/entrypoint.sh b/services/comfy-cuda/entrypoint.sh similarity index 55% rename from services/comfy/entrypoint.sh rename to services/comfy-cuda/entrypoint.sh index b4299a7..6abbf08 100755 --- a/services/comfy/entrypoint.sh +++ b/services/comfy-cuda/entrypoint.sh @@ -8,6 +8,8 @@ declare -A MOUNTS MOUNTS["/root/.cache"]="/data/.cache" MOUNTS["${ROOT}/input"]="/data/config/comfy/input" +MOUNTS["${ROOT}/custom_nodes"]="/data/config/comfy/custom_nodes" +MOUNTS["${ROOT}/my_workflows"]="/data/config/comfy/my_workflows" MOUNTS["${ROOT}/output"]="/output/comfy" for to_path in "${!MOUNTS[@]}"; do @@ -22,6 +24,14 @@ for to_path in "${!MOUNTS[@]}"; do echo Mounted $(basename "${from_path}") done +if [ -z "$(ls -A /data/config/comfy/custom_nodes/ComfyUI_UltimateSDUpscale)" ]; then + git -C /data/config/comfy/custom_nodes clone https://github.com/ssitu/ComfyUI_UltimateSDUpscale --recursive +fi + +if [ -z "$(ls -A /data/config/comfy/custom_nodes/comfyui-workspace-manager)" ]; then + git -C /data/config/comfy/custom_nodes clone https://github.com/11cafe/comfyui-workspace-manager.git +fi + if [ -f "/data/config/comfy/startup.sh" ]; then pushd ${ROOT} . /data/config/comfy/startup.sh diff --git a/services/comfy/extra_model_paths.yaml b/services/comfy-cuda/extra_model_paths.yaml similarity index 100% rename from services/comfy/extra_model_paths.yaml rename to services/comfy-cuda/extra_model_paths.yaml diff --git a/services/comfy/Dockerfile b/services/comfy-rocm/Dockerfile similarity index 77% rename from services/comfy/Dockerfile rename to services/comfy-rocm/Dockerfile index ea02d16..617e30a 100644 --- a/services/comfy/Dockerfile +++ b/services/comfy-rocm/Dockerfile @@ -1,4 +1,3 @@ -# FROM pytorch/pytorch:2.1.2-cuda12.1-cudnn8-runtime FROM rocm/pytorch:rocm6.1_ubuntu22.04_py3.10_pytorch_2.1.2 ENV DEBIAN_FRONTEND=noninteractive PIP_PREFER_BINARY=1 @@ -10,14 +9,13 @@ RUN --mount=type=cache,target=/root/.cache/pip,Z \ git clone --recursive https://github.com/comfyanonymous/ComfyUI.git ${ROOT} && \ cd ${ROOT} && \ git checkout master && \ -# git reset --hard d1f3637a5a944d0607b899babd8ff11d87100503 && \ + git reset --hard 5eb98f00927ace00b6b3d01ed9c76b113fc4ec9f && \ pip install -r requirements.txt WORKDIR ${ROOT} COPY . /docker/ RUN chmod u+x /docker/entrypoint.sh && cp /docker/extra_model_paths.yaml ${ROOT} -# ENV NVIDIA_VISIBLE_DEVICES=all PYTHONPATH="${PYTHONPATH}:${PWD}" CLI_ARGS="" ENV PYTHONPATH="${PYTHONPATH}:${PWD}" CLI_ARGS="" EXPOSE 7860 ENTRYPOINT ["/docker/entrypoint.sh"] diff --git a/services/comfy-rocm/entrypoint.sh b/services/comfy-rocm/entrypoint.sh new file mode 100755 index 0000000..6abbf08 --- /dev/null +++ b/services/comfy-rocm/entrypoint.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -Eeuo pipefail + +mkdir -vp /data/config/comfy/custom_nodes + +declare -A MOUNTS + +MOUNTS["/root/.cache"]="/data/.cache" +MOUNTS["${ROOT}/input"]="/data/config/comfy/input" +MOUNTS["${ROOT}/custom_nodes"]="/data/config/comfy/custom_nodes" +MOUNTS["${ROOT}/my_workflows"]="/data/config/comfy/my_workflows" +MOUNTS["${ROOT}/output"]="/output/comfy" + +for to_path in "${!MOUNTS[@]}"; do + set -Eeuo pipefail + from_path="${MOUNTS[${to_path}]}" + rm -rf "${to_path}" + if [ ! -f "$from_path" ]; then + mkdir -vp "$from_path" + fi + mkdir -vp "$(dirname "${to_path}")" + ln -sT "${from_path}" "${to_path}" + echo Mounted $(basename "${from_path}") +done + +if [ -z "$(ls -A /data/config/comfy/custom_nodes/ComfyUI_UltimateSDUpscale)" ]; then + git -C /data/config/comfy/custom_nodes clone https://github.com/ssitu/ComfyUI_UltimateSDUpscale --recursive +fi + +if [ -z "$(ls -A /data/config/comfy/custom_nodes/comfyui-workspace-manager)" ]; then + git -C /data/config/comfy/custom_nodes clone https://github.com/11cafe/comfyui-workspace-manager.git +fi + +if [ -f "/data/config/comfy/startup.sh" ]; then + pushd ${ROOT} + . /data/config/comfy/startup.sh + popd +fi + +exec "$@" diff --git a/services/comfy-rocm/extra_model_paths.yaml b/services/comfy-rocm/extra_model_paths.yaml new file mode 100644 index 0000000..eb374eb --- /dev/null +++ b/services/comfy-rocm/extra_model_paths.yaml @@ -0,0 +1,25 @@ +a111: + base_path: /data + + checkpoints: models/Stable-diffusion + configs: models/Stable-diffusion + vae: models/VAE + loras: models/Lora + upscale_models: | + models/RealESRGAN + models/ESRGAN + models/SwinIR + models/GFPGAN + hypernetworks: models/hypernetworks + controlnet: models/ControlNet + gligen: models/GLIGEN + clip: models/CLIPEncoder + embeddings: embeddings + + custom_nodes: config/comfy/custom_nodes + + # TODO: I am unsure about these, need more testing + # style_models: config/comfy/style_models + # t2i_adapter: config/comfy/t2i_adapter + # clip_vision: config/comfy/clip_vision + # diffusers: config/comfy/diffusers