Read our article here: https://blib.la/blog/comfyui-on-runpod
- Quickstart
- Features
- Config
- Use the Docker image on RunPod
- API specification
- Interact with your RunPod API
- How to get the workflow from ComfyUI?
- Build the image
- Local testing
- Automatically deploy to Docker hub with Github Actions
- Acknowledgments
- 🐳 Use the latest image for your worker: timpietruskyblibla/runpod-worker-comfy:latest
- ⚙️ Set the environment variables
- ℹ️ Use the Docker image on RunPod
- Run any ComfyUI workflow to generate an image
- Provide input images as base64-encoded string
- The generated image is either:
- Returned as base64-encoded string (default)
- Uploaded to AWS S3 (if AWS S3 is configured)
- Build-in checkpoint:
- Build-in VAE:
- Build-in LoRA:
- xl_more_art-full_v1.safetensors (Enhancer)
- Based on Ubuntu + NVIDIA CUDA
Environment Variable | Description | Default |
---|---|---|
REFRESH_WORKER |
When you want stop the worker after each finished job to have a clean state, see official documentation. | false |
This is only needed if you want to upload the generated picture to AWS S3. If you don't configure this, your image will be exported as base64-encoded string.
- Create a bucket in region of your choice in AWS S3 (
BUCKET_ENDPOINT_URL
) - Create an IAM that has access rights to AWS S3
- Create an Access-Key (
BUCKET_ACCESS_KEY_ID
&BUCKET_SECRET_ACCESS_KEY
) for that IAM - Configure these environment variables for your RunPod worker:
Environment Variable | Description | Example |
---|---|---|
BUCKET_ENDPOINT_URL |
The endpoint URL of your S3 bucket. | https://<bucket>.s3.<region>.amazonaws.com |
BUCKET_ACCESS_KEY_ID |
Your AWS access key ID for accessing the S3 bucket. | AKIAIOSFODNN7EXAMPLE |
BUCKET_SECRET_ACCESS_KEY |
Your AWS secret access key for accessing the S3 bucket. | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |
- Create a new template by clicking on
New Template
- In the dialog, configure:
- Template Name:
runpod-worker-comfy
(it can be anything you want) - Container Image:
<dockerhub_username>/<repository_name>:tag
, in this case:timpietruskyblibla/runpod-worker-comfy:latest
(ordev
if you want to have the development release) - Container Registry Credentials: You can leave everything as it is, as this repo is public
- Container Disk:
20 GB
- Enviroment Variables: Configure S3
- Note: You can also not configure it, the images will then stay in the worker. In order to have them stored permanently, we have to add the network volume
- Template Name:
- Click on
Save Template
- Navigate to
Serverless > Endpoints
and click onNew Endpoint
- In the dialog, configure:
- Endpoint Name:
comfy
- Select Template:
runpow-worker-comfy
(or whatever name you gave your template) - Active Workers:
0
(whatever makes sense for you) - Max Workers:
3
(whatever makes sense for you) - Idle Timeout:
5
(you can leave the default) - Flash Boot:
enabled
(doesn't cost more, but provides faster boot of our worker, which is good) - Advanced: Leave the defaults
- Select a GPU that has some availability
- GPUs/Worker:
1
- Endpoint Name:
- Click
deploy
- Your endpoint will be created, you can click on it to see the dashboard
The following describes which fields exist when doing requests to the API. We only describe the fields that are sent via input
as those are needed by the worker itself. For a full list of fields, please take a look at the official documentation.
{
"input": {
"workflow": {},
"images": [
{
"name": "example_image_name.png",
"image": "base64_encoded_string"
}
]
}
}
Field Path | Type | Required | Description |
---|---|---|---|
input |
Object | Yes | The top-level object containing the request data. |
input.workflow |
Object | Yes | Contains the ComfyUI workflow configuration. |
input.images |
Array | No | An array of images. Each image will be added into the "input"-folder of ComfyUI and can then be used in the workflow by using it's name |
An array of images, where each image should have a different name.
🚨 The request body for a RunPod endpoint is 10 MB for /run
and 20 MB for /runsync
, so make sure that your input images are not super huge as this will be blocked by RunPod otherwise, see the official documentation
Field Name | Type | Required | Description |
---|---|---|---|
name |
String | Yes | The name of the image. Please use the same name in your workflow to reference the image. |
image |
String | Yes | A base64 encoded string of the image. |
- In the User Settings click on
API Keys
and then on theAPI Key
button - Save the generated key somewhere, as you will not be able to see it again when you navigate away from the page
- Use cURL or any other tool to access the API using the API key and your Endpoint-ID:
- Replace
<api_key>
with your key - Replace
<endpoint_id>
with the ID of the endpoint, you find that when you click on your endpoint, it's part of the URLs shown at the bottom of the first box
- Replace
curl -H "Authorization: Bearer <api_key>" https://api.runpod.ai/v2/<endpoint_id>/health
You can either create a new job async by using /run
or a sync by using runsync. The example here is using a sync job and waits until the response is delivered.
The API expects a JSON in this form, where workflow
is the workflow from ComfyUI, exported as JSON and images
is optional.
Please also take a look at the test_input.json to see how the API input should look like.
curl -X POST -H "Authorization: Bearer <api_key>" -H "Content-Type: application/json" -d '{"input":{"workflow":{"3":{"inputs":{"seed":1337,"steps":20,"cfg":8,"sampler_name":"euler","scheduler":"normal","denoise":1,"model":["4",0],"positive":["6",0],"negative":["7",0],"latent_image":["5",0]},"class_type":"KSampler"},"4":{"inputs":{"ckpt_name":"sd_xl_base_1.0.safetensors"},"class_type":"CheckpointLoaderSimple"},"5":{"inputs":{"width":512,"height":512,"batch_size":1},"class_type":"EmptyLatentImage"},"6":{"inputs":{"text":"beautiful scenery nature glass bottle landscape, purple galaxy bottle,","clip":["4",1]},"class_type":"CLIPTextEncode"},"7":{"inputs":{"text":"text, watermark","clip":["4",1]},"class_type":"CLIPTextEncode"},"8":{"inputs":{"samples":["3",0],"vae":["4",2]},"class_type":"VAEDecode"},"9":{"inputs":{"filename_prefix":"ComfyUI","images":["8",0]},"class_type":"SaveImage"}}}}' https://api.runpod.ai/v2/<endpoint_id>/runsync
# Response with AWS S3 bucket configuration
# {"delayTime":2188,"executionTime":2297,"id":"sync-c0cd1eb2-068f-4ecf-a99a-55770fc77391-e1","output":{"message":"https://bucket.s3.region.amazonaws.com/10-23/sync-c0cd1eb2-068f-4ecf-a99a-55770fc77391-e1/c67ad621.png","status":"success"},"status":"COMPLETED"}
# Response as base64-encoded image
# {"delayTime":2188,"executionTime":2297,"id":"sync-c0cd1eb2-068f-4ecf-a99a-55770fc77391-e1","output":{"message":"base64encodedimage","status":"success"},"status":"COMPLETED"}
- Open ComfyUI in the browser
- Open the
Settings
(gear icon in the top right of the menu) - In the dialog that appears configure:
Enable Dev mode Options
: enable- Close the
Settings
- In the menu, click on the
Save (API Format)
button, which will download a file namedworkflow_api.json
You can now take the content of this file and put it into your workflow
when interacting with the API.
You can build the image locally: docker build -t timpietruskyblibla/runpod-worker-comfy:dev --platform linux/amd64 .
🚨 It's important to specify the --platform linux/amd64
, otherwise you will get an error on RunPod, see #13
Both tests will use the data from test_input.json, so make your changes in there to test this properly.
- Make sure you have Python >= 3.10
- Create a virtual environment:
python -m venv venv
- Activate the virtual environment:
.\venv\Scripts\activate
(Windows) orsource ./venv/bin/activate
(Mac / Linux) - Install the dependencies:
pip install -r requirements.txt
Note: Our hope was that we can use this Docker Image with Docker Desktop on Windows. But regardless what we did, it was not possible. So we decided to use Ubuntu as part of WSL (Windows Subsystem for Linux) inside of Windows. This works without any problems, but only if you don't run Docker on Windows itself.
To run the Docker image on Windows, we need to have WSL2 and a Linux distro (like Ubuntu) installed on Windows.
- Follow the guide on how to get WSL2 and Linux installed in Windows to install Ubuntu
- You can skip the "Install and use a GUI package" part as we don't need a GUI
- When Ubuntu is installed, you have to login to Ubuntu in the terminal:
wsl -d Ubuntu
- Update the packages:
sudo apt update
- Install Docker in Ubuntu & then install docker-compose
sudo apt-get install docker-compose
- Install the NVIDIA Toolkit in Ubuntu and create the
nvidia
runtime
-
Enable GPU acceleration on Ubuntu on WSL2 to use NVIDIA CUDA
- For the step "Install the appropriate Windows vGPU driver for WSL": If you already have your GPU driver installed on Windows, you can skip this
-
Add your user to the
docker
group, so that you can use Docker withoutsudo
:sudo usermod -aG docker $USER
- Run all tests:
python -m unittest discover
- If you want to run a specific test:
python -m unittest tests.test_rp_handler.TestRunpodWorkerComfy.test_bucket_endpoint_not_configured
You can also start the handler itself to have the local server running: python src/rp_handler.py
To get this to work you will also need to start "ComfyUI", otherwise the handler will not work.
For enhanced local development, you can start an API server that simulates the RunPod worker environment. This feature is particularly useful for debugging and testing your integrations locally.
Set the SERVE_API_LOCALLY
environment variable to true
to activate the local API server when running your Docker container. This is already the default value in the docker-compose.yml
, so you can get it runnig by executing:
docker-compose up
- With the local API server running, it's accessible at: http://localhost:8000
- When you open this in your browser, you can also see the API documentation and can interact with the API directly
The repo contains two workflows that publish the image to Docker hub using Github Actions:
- docker-dev.yml: Creates the image and pushes it to Docker hub with the
dev
tag on every push to themain
branch - docker-release.yml: Creates the image and pushes it to Docker hub with the
latest
and the release tag. It will only be triggered when you create a release on GitHub
If you want to use this, you should add these secrets to your repository:
Configuration Variable | Description | Example Value |
---|---|---|
DOCKERHUB_USERNAME |
Your Docker Hub username. | your-username |
DOCKERHUB_TOKEN |
Your Docker Hub token for authentication. | your-token |
DOCKERHUB_REPO |
The repository on Docker Hub where the image will be pushed. | timpietruskyblibla |
DOCKERHUB_IMG |
The name of the image to be pushed to Docker Hub. | runpod-worker-comfy |
- Thanks to all contributors for your awesome work
- Thanks to Justin Merrell from RunPod for worker-1111, which was used to get inspired on how to create this worker
- Thanks to Ashley Kleynhans for runpod-worker-a1111, which was used to get inspired on how to create this worker
- Thanks to comfyanonymous for creating ComfyUI, which provides such an awesome API to interact with Stable Diffusion