/runpod-worker-comfy

ComfyUI as a serverless API on RunPod

Primary LanguagePythonGNU Affero General Public License v3.0AGPL-3.0

runpod-worker-comfy

ComfyUI as a serverless API on RunPod



Quickstart

Features

Config

Upload image to AWS S3

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

Use the Docker image on RunPod

  • 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 (or dev 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
  • Click on Save Template
  • Navigate to Serverless > Endpoints and click on New Endpoint
  • In the dialog, configure:
    • Endpoint Name: comfy
    • Select Template: runpow-worker-comfy (or what ever name you gave your template)
    • Active Workers: 0 (what ever makes sense for you)
    • Max Workers: 3 (what ever 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
  • Click deploy
  • Your endpoint will be created, you can click on it to see the dashboard

Interact with your RunPod API

  • In the User Settings click on API Keys and then on the API 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

Health status

curl -H "Authorization: Bearer <api_key>" https://api.runpod.ai/v2/<endpoint_id>/health

Generate an image

You can ether 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 prompt is the workflow from ComfyUI, exported as JSON:

{
  "input": {
    "prompt": {
      // ComfyUI workflow
    }
  }
}

Please also take a look at the test_input.json to see how the API input should look like.

Example request with cURL

curl -X POST -H "Authorization: Bearer <api_key>" -H "Content-Type: application/json" -d '{"input":{"prompt":{"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
#

How to get the workflow from ComfyUI?

  • 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 named workflow_api.json

You can now take the content of this file and put it into your prompt when interacting with the API.

Build the image

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

Local testing

Both tests will use the data from test_input.json, so make your changes in there to test this properly.

Setup

  • Make sure you have Python >= 3.10
  • Create a virtual environment: python -m venv venv
  • Install the dependencies: pip install -r requirements.txt

Setup for Windows

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.

  • 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 without sudo: sudo usermod -aG docker $USER

Activate virtual env

.\venv\Scripts\activate

Test: handler

  • 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 In order to get this to work you will also need to start "ComfyUI", otherwise the handler will not work.

Test: docker image

  • If you want to run the Docker container, you can use: docker-compose up

Automatically deploy to Docker hub with Github Actions

The repo contains two workflows that publishes 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 the main 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

Acknowledgements