{"id":22466728,"url":"https://github.com/blib-la/runpod-worker-helloworld","last_synced_at":"2025-09-02T21:44:23.810Z","repository":{"id":198911024,"uuid":"701797445","full_name":"blib-la/runpod-worker-helloworld","owner":"blib-la","description":"Getting started with a serverless endpoint on RunPod by creating a custom worker","archived":false,"fork":false,"pushed_at":"2023-12-11T21:11:52.000Z","size":132,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-02T08:27:23.858Z","etag":null,"topics":["ai","api","runpod","runpod-worker","serverless"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blib-la.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-10-07T15:30:43.000Z","updated_at":"2025-03-13T12:50:29.000Z","dependencies_parsed_at":"2025-08-02T07:31:20.644Z","dependency_job_id":"f0349ca8-7d98-43a9-8618-67c7d61d5d47","html_url":"https://github.com/blib-la/runpod-worker-helloworld","commit_stats":null,"previous_names":["blib-la/runpod-worker-helloworld"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/blib-la/runpod-worker-helloworld","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blib-la%2Frunpod-worker-helloworld","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blib-la%2Frunpod-worker-helloworld/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blib-la%2Frunpod-worker-helloworld/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blib-la%2Frunpod-worker-helloworld/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blib-la","download_url":"https://codeload.github.com/blib-la/runpod-worker-helloworld/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blib-la%2Frunpod-worker-helloworld/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273355648,"owners_count":25090825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","api","runpod","runpod-worker","serverless"],"created_at":"2024-12-06T10:13:23.331Z","updated_at":"2025-09-02T21:44:23.705Z","avatar_url":"https://github.com/blib-la.png","language":"Python","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003erunpod-worker-helloworld\u003c/h1\u003e\n\n  \u003cblockquote\u003eGetting started with a serverless endpoint on \u003ca href=\"https://www.runpod.io/\"\u003eRunPod\u003c/a\u003e by creating a custom worker\u003c/blockquote\u003e\n\n  \u003cimg src=\"assets/construction_site_with_banner_reading_runpod_worker_hello_world.jpg\" title=\"Construction site with a large banner that reads 'RunPod Worker Hello World'\" /\u003e\n\u003c/div\u003e\n\n---\n\n\u003c!-- toc --\u003e\n\n- [Features](#features)\n- [Setup](#setup)\n- [Local testing](#local-testing)\n  * [Run the handler](#run-the-handler)\n  * [Unit Tests](#unit-tests)\n  * [Run the Docker image](#run-the-docker-image)\n- [Build and release your Docker image](#build-and-release-your-docker-image)\n  * [Automatically with GitHub Actions](#automatically-with-github-actions)\n    + [Configuration](#configuration)\n    + [Dev Workflow](#dev-workflow)\n    + [Release Workflow](#release-workflow)\n  * [Manually](#manually)\n    + [Build the Docker image](#build-the-docker-image)\n    + [Push the Docker image to Docker Hub](#push-the-docker-image-to-docker-hub)\n- [Use your Docker image on RunPod serverless](#use-your-docker-image-on-runpod-serverless)\n- [Interact with your RunPod endpoint](#interact-with-your-runpod-endpoint)\n  * [Health status of your endpoint](#health-status-of-your-endpoint)\n  * [Start an async job](#start-an-async-job)\n  * [Start a sync job](#start-a-sync-job)\n  * [Get the status of a specific job](#get-the-status-of-a-specific-job)\n- [Where to go from here?](#where-to-go-from-here)\n- [Acknowledgments](#acknowledgments)\n- [Credits](#credits)\n\n\u003c!-- tocstop --\u003e\n\n---\n\n## Features\n\nThis project provides a set of starting points for creating your worker (= Docker image) to create a custom serverless endpoint on [RunPod](https://www.runpod.io/):\n\n* Simple [start script](src/start.sh) that makes sure to start the handler and whatever you need your worker to have, so that it can do its work (like starting [ComfyUI](https://github.com/comfyanonymous/ComfyUI))\n* Basic [handler]([src/rp_handler.py](src/rp_handler.py)), that you can extend with the business logic that you need for your use case\n* GitHub [dev](#dev-workflow) workflow during the development of your Docker image\n* GitHub [release](#release-workflow) workflow when you want to publish a fully automated new version of your Docker image\n* Foundation for [unit tests](/tests) to get started with Test-driven development (TDD)\n\n## Setup\n\n* Clone the repo to your computer\n* Create a virtual environment: `python -m venv venv`\n* Activate the virtual environment: \n  * Windows: `.\\venv\\Scripts\\activate` \n  * Mac / Linux: `source ./venv/bin/activate`\n* Install the dependencies: `pip install -r requirements.txt`\n* Make sure to have [Docker installed on your computer](https://www.docker.com/get-started/) if you want to build the image locally\n\n## Local testing\n\n### Run the handler\n\nExecute `python src/rp_handler.py`, which will then output something like this:\n\n```bash\n--- Starting Serverless Worker |  Version 1.3.7 ---\nINFO   | Using test_input.json as job input.\nDEBUG  | Retrieved local job: {'input': {'greeting': 'world'}, 'id': 'local_test'}\nINFO   | local_test | Started\nDEBUG  | local_test | Handler output: Hello world\nDEBUG  | local_test | run_job return: {'output': 'Hello world'}\nINFO   | Job local_test completed successfully.\nINFO   | Job result: {'output': 'Hello world'}\nINFO   | Local testing complete, exiting.\n```\n\n### Unit Tests\n\nRun all tests: `python -m unittest discover`, which will then output something like this:\n\n```bash\n...\n----------------------------------------------------------------------\nRan 3 tests in 0.000s\n\nOK\n```\n\n### Run the Docker image\n\nWe included a [docker-compose.yml](docker-compose.yml) which makes it possible to easily run the Docker image locally: `docker-compose up`\n\nThis will only work for Linux-based systems, as we only create an image for Linux, as this is what RunPod requires. To do this for Mac or Windows, you have to follow the steps to [build the image manually](#build-the-docker-image). Make sure to build the image with the `dev` tag, as this is used in the [docker-compose.yml](docker-compose.yml).  \n\n\n## Build and release your Docker image\n\nTo use your Docker image on [RunPod](https://www.runpod.io/), it must exist in a Docker image registry. We are using [Docker Hub](https://hub.docker.com) for this, but feel free to choose whatever you want. \n\n### Automatically with GitHub Actions\n\nThe repo contains two workflows that publish the image to [Docker Hub](https://hub.docker.com) using GitHub Actions: [dev.yml](.github/workflows/dev.yml) and [release.yml](.github/workflows/release.yml). \n\nThis process is highly opinionated and you should adapt it to what you are used to. \n\n#### Configuration\n\nIf you want to use these workflows, you have to add these secrets to your repository:\n\n| Configuration Variable | Description                                                  | Example Value              |\n| ---------------------- | ------------------------------------------------------------ | -------------------------- |\n| `DOCKERHUB_USERNAME`   | Your Docker Hub username.                                    | `your-username`            |\n| `DOCKERHUB_TOKEN`      | Your Docker Hub token for authentication.                    | `your-token`               |\n| `DOCKERHUB_REPO`       | The repository on Docker Hub where the image will be pushed. | `timpietruskyblibla`       |\n| `DOCKERHUB_IMG`        | The name of the image to be pushed to Docker Hub.            | `runpod-worker-helloworld` |\n\n#### Dev Workflow\n\nWhen you are developing your image and want to provide bug fixes or features to your community, you can put them into the `dev` branch. This will trigger the [dev](.github/workflows/dev.yml) workflow, which runs these steps: \n\n* Execute the unit tests\n* Build the image\n* Push the image to [Docker Hub](https://hub.docker.com) using the `dev` tag\n\n#### Release Workflow\n\nWhen development is done and you are ready for a new release of your image, you can put all your changes into the `main` branch. This will trigger the [release](.github/workflows/release.yml) workflow, which runs these steps:\n\n* Execute the unit tests\n* Update \"Table of Contents\" in the `README.md`\n* Create a release on GitHub using [Semantic Versioning](https://semver.org) based on [semantic-release](https://semantic-release.gitbook.io) (which only works if you follow one of the [commit message formats](https://semantic-release.gitbook.io/semantic-release/#commit-message-format), the default are the [Angular Commit Message Conventions](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format) as you can also see in this repo)\n* Update the `CHANGELOG.md`\n* Build the image\n* Push the image to [Docker Hub](https://hub.docker.com) and tag it with both the release version and `latest`\n* Update the description of the image on [Docker Hub](https://hub.docker.com)\n\n### Manually\n\n#### Build the Docker image\n\n* Build your Docker image like this `docker build -t \u003cdockerhub_username\u003e/\u003crepository_name\u003e:\u003ctag\u003e --platform linux/amd64 .`, in this case: `docker build -t timpietruskyblibla/runpod-worker-helloworld:latest --platform linux/amd64 .`\n  * We need to specify the platform here, as this is what RunPod requires. If you don't do this, you might see an error like `exec python failed: Exec format error` when you run your worker on RunPod, depending on the OS you are using locally\n  * If you want to run your image locally and you are not using a Linux-based OS, then you have to use the appropriate platform:\n    * Windows: `docker build -t \u003cdockerhub_username\u003e/\u003crepository_name\u003e:\u003ctag\u003e --platform windows/amd64 .`\n    * MacOS with Apple Silicon: `docker build -t \u003cdockerhub_username\u003e/\u003crepository_name\u003e:\u003ctag\u003e --platform linux/arm64 .`\n* After the image is created, you can see it when you run `docker images`, which provides a list of all images that exist on your computer\n\n#### Push the Docker image to Docker Hub\n\n* Create an account on [Docker Hub](https://hub.docker.com/) if you don't have one already\n* Login to your account: `docker login`\n* Push your Docker image to [Docker Hub](https://hub.docker.com/) like this `docker push \u003cdockerhub_username\u003e/\u003crepository_name\u003e:\u003ctag\u003e`, in this case: `docker push timpietruskyblibla/runpod-worker-helloworld:latest`\n* Once this is done, you can check your [Docker Hub](https://hub.docker.com/) account to find the image\n\n\n## Use your Docker image on RunPod serverless\n\n* Create a [new template](https://runpod.io/console/serverless/user/templates) by clicking on `New Template` \n* In the dialog, configure:\n  * Template Name: `runpod-worker-helloworld` (it can be anything you want)\n  * Container Image: `\u003cdockerhub_username\u003e/\u003crepository_name\u003e:tag`, in this case: `timpietruskyblibla/runpod-worker-helloworld:latest`\n* You can leave everything as it is, as this repo is public\n* Click on `Save Template`\n* Navigate to [`Serverless \u003e Endpoints`](https://www.runpod.io/console/serverless/user/endpoints) and click on `New Endpoint`\n* In the dialog, configure:\n  * Endpoint Name: `hellworld`\n  * Select Template: `runpow-worker-helloworld` (or what ever name you gave your template)\n  * Active Workers: `0` (keep this low, as we just want to test the Hello World)\n  * Max Workers: `3` (recommended default is 3)\n  * Idle Timeout: `5` (leave the default)\n  * Flash Boot: `enabled` (doesn't cost more, but provides faster boot for our worker, which is good)\n  * Advanced: Leave the defaults\n  * Select a GPU that has some availability\n  * GPUs/Worker: `1` (keep this low as we are just testing, we don't need multiple GPUs for a hello world)\n* Click `deploy`\n* Your endpoint will be created, you can click on it to see the dashboard and also the available API methods:\n  * `runsync`: Sync request to start a job, where you can wait for the job result\n  * `run`: Async request to start a job, where you receive an `id` immediately\n  * `status`: Sync request to find out what the status of a job is, given `id`\n  * `cancel`: Sync request to cancel a job, given `id`\n  * `health`: Sync request to check the health of the endpoint to see if everything is fine\n\n## Interact with your RunPod endpoint\n\n* In the [User Settings](https://www.runpod.io/console/serverless/user/settings) click on `API Keys` and then on the `API Key` button\n* Save the generated key somewhere, as you will not be able to see it again when you navigate away from the page\n* Use cURL or any other tool to access the API using the API key and your Endpoint-ID:\n  * Replace `\u003capi_key\u003e` with your key\n  * Replace `\u003cendpoint_id\u003e` 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\n\n### Health status of your endpoint\n\n```bash\ncurl -H \"Authorization: Bearer \u003capi_key\u003e\" https://api.runpod.ai/v2/\u003cendpoint_id\u003e/health\n```\n\n### Start an async job\n\nThis will return an `id` that you can then use in the `status` endpoint to find out if your job was completed. \n\n```bash\n# Returns a JSON with the id of the job (\u003cjob_id\u003e), use that in the status endpoint\ncurl -X POST -H \"Authorization: Bearer \u003capi_key\u003e\" -H \"Content-Type: application/json\" -d '{\"input\": {\"greeting\": \"world\"}}' https://api.runpod.ai/v2/\u003cendpoint_id\u003e/run\n\n# {\"id\":\"\u003cjob_id\u003e\",\"status\":\"IN_QUEUE\"}\n```\n\n### Start a sync job\n\nThis endpoint will wait until the job is done and provide the output of our API as the response.\n\nIf you do a sync request to an endpoint that has no free workers to pick up the job, you will wait for some time. Either your job will be picked up if a worker gets free or the job gets added to the queue (provided by the endpoint), which will result in you receiving an `id`. You then have to manually ask the `/status` endpoint to get information about when the job was completed. \n\n```bash\ncurl -X POST -H \"Authorization: Bearer \u003capi_key\u003e\" -H \"Content-Type: application/json\" -d '{\"input\": {\"greeting\": \"world\"}}' https://api.runpod.ai/v2/\u003cendpoint_id\u003e/runsync\n\n# {\"delayTime\":2218,\"executionTime\":138,\"id\":\"\u003cjob_id\u003e\",\"output\":\"Hello world\",\"status\":\"COMPLETED\"}\n```\n\n### Get the status of a specific job\n\n```bash\ncurl -H \"Authorization: Bearer \u003capi_key\u003e\" https://api.runpod.ai/v2/\u003cendpoint_id\u003e/status/\u003cjob_id\u003e\n\n# {\"delayTime\":3289,\"executionTime\":1054,\"id\":\"\u003cjob_id\u003e\",\"output\":\"Hello world\",\"status\":\"COMPLETED\"}\n```\n\n## Where to go from here?\n\n* [RunPod Workers](https://github.com/runpod-workers): A list of workers provided by RunPod\n\n## Acknowledgments\n\n* Thanks to [Justin Merrell](https://github.com/justinmerrell) from RunPod for [this nice getting started guide](https://blog.runpod.io/serverless-create-a-basic-api/) that was used to create this hello-world guide\n\n## Credits\n\n* The [title image](/assets/construction_site_with_banner_reading_runpod_worker_hello_world.jpg) was generated with [Broom](https://broom.blib.la) (which runs on RunPod using [runpod-worker-comfy](https://github.com/blib-la/runpod-worker-comfy) to generate images with text in [ComfyUI](https://github.com/comfyanonymous/ComfyUI) using SDXL 1.0)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblib-la%2Frunpod-worker-helloworld","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblib-la%2Frunpod-worker-helloworld","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblib-la%2Frunpod-worker-helloworld/lists"}