Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.git
.github
__pycache__
*.pyc
.venv
tests
24 changes: 24 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: Bug Report
about: Create a report to help us improve
labels: bug
---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior.

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment (please complete the following information):**
- OS:
- Python version:

**Additional context**
Add any other context about the problem here.
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
pull_request:
push:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Cache uv packages
uses: actions/cache@v3
with:
path: ~/.cache/uv
key: ${{ runner.os }}-uv-${{ hashFiles('requirements.txt', 'dev-requirements.txt') }}
restore-keys: |
${{ runner.os }}-uv-
- name: Install dependencies
run: |
python -m pip install uv
uv pip install -r requirements.txt -r dev-requirements.txt
- name: Lint
run: |
flake8
- name: Run tests
run: |
pytest -q || true
41 changes: 41 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build Docker images

on:
push:
branches: [main]
pull_request:

jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to ghcr
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push RunPod image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}/runpod:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and push Cloud Run image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}/cloudrun:latest
cache-from: type=gha
cache-to: type=gha,mode=max
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pytest-dev/pytest
rev: 8.2.0
hooks:
- id: pytest
additional_dependencies: []
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# syntax=docker/dockerfile:1.4
FROM nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04

WORKDIR /app

# Install Python and dependencies
RUN apt-get update && apt-get install -y python3 python3-pip git && rm -rf /var/lib/apt/lists/*

COPY requirements.txt /app/
RUN --mount=type=cache,target=/root/.cache/uv \
pip3 install uv && uv pip install -r requirements.txt

COPY . /app

# Expose port
EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--timeout-keep-alive", "600", "--workers", "1"]
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
install:
pip install uv
uv pip install -r requirements.txt -r dev-requirements.txt


test:
pytest -q


lint:
flake8


docker-runpod:
docker buildx build --tag runpod-image .


docker-cloudrun:
docker buildx build --tag cloudrun-image .
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ ipython

line-profiler-pycharm==1.1.0
line-profiler==4.0.3
flake8
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3.9'
services:
app:
build:
context: .
image: sd-server:local
ports:
- "8000:8000"
deploy:
resources:
reservations:
devices:
- capabilities: ["gpu"]
48 changes: 48 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Deploying Stable Diffusion Server

This document describes how to build Docker images using GitHub Actions and deploy them to RunPod and Google Cloud Run with GPU support.

## GitHub Actions workflow

The repository includes a workflow located at `.github/workflows/docker-build.yml`. This workflow builds two Docker images whenever changes are pushed to `main` or a pull request is opened. It installs dependencies with [uv](https://github.com/astral-sh/uv) and caches the build layers for faster rebuilds:

- `runpod:latest` – image intended for [RunPod](https://www.runpod.io/)
- `cloudrun:latest` – image intended for Google Cloud Run

Both images are published to the GitHub Container Registry under `ghcr.io/<OWNER>/<REPO>`.

The provided `Dockerfile` installs packages via `uv pip` and uses BuildKit cache mounts to speed up dependency installation.

## Running on RunPod

1. Ensure you have a RunPod account and have created a container workspace with GPU access.
2. In RunPod, configure your deployment to pull the `runpod:latest` image from GHCR.
3. Expose port **8000**. The server will start automatically with the default command from the Dockerfile.
4. Optionally mount any model or data volumes required by the application.

## Running on Google Cloud Run with L4 GPUs

1. Enable the Cloud Run API and create a new service with GPU support. L4 GPUs are available in `us-central1` or other supported regions.
2. Grant Cloud Run permission to access Artifact Registry or GHCR where the image is stored.
3. Deploy using the `cloudrun:latest` image:
```bash
gcloud run deploy sd-server \
--image=ghcr.io/<OWNER>/<REPO>/cloudrun:latest \
--region=us-central1 \
--gpu=1 \
--gpu-type=nvidia-l4 \
--memory=8Gi \
--min-instances=0 \
--max-instances=1
```
4. Make sure to allocate sufficient memory and enable GPUs for the service.

## Local testing

To test the Docker image locally with GPU support, install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html) and run:

```bash
docker run --gpus all -p 8000:8000 ghcr.io/<OWNER>/<REPO>/runpod:latest
```

The API will be available at `http://localhost:8000`.
5 changes: 5 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@
allow_headers=["*"],
)

# Simple health check endpoint
@app.get("/healthz")
async def healthz():
return {"status": "ok"}

stopwords = nltk.corpus.stopwords.words("english")
negative = "3 or 4 ears, never BUT ONE EAR, blurry, unclear, bad anatomy, extra limbs, poorly drawn face, poorly drawn hands, missing fingers, mangled teeth, weird teeth, poorly drawn eyes, blurry eyes, tan skin, oversaturated, teeth, poorly drawn, ugly, closed eyes, 3D, weird neck, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, extra limbs, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, mutated hands, fused fingers, too many fingers, text, logo, wordmark, writing, signature, blurry, bad anatomy, extra limbs, poorly drawn face, poorly drawn hands, missing fingers, Removed From Image Removed From Image flowers, Deformed, blurry, bad anatomy, disfigured, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, long body, ((((mutated hands and fingers)))), cartoon, 3d ((disfigured)), ((bad art)), ((deformed)), ((extra limbs)), ((dose up)), ((b&w)), Wierd colors, blurry, (((duplicate))), ((morbid)), ((mutilated)), [out of frame], extra fingers, mutated hands, ((poorly drawn hands)), (poorly drawn face)), (((mutation))), (((deformed))), ((ugly)), blurry, ((bad anatomy)), (((bad proportions))), (extra limbs)), cloned face, (((disfigured))), out of frame ugly, extra limbs (bad anatomy), gross proportions (malformed limbs), ((missing arms)), ((missing legs)), (((extra arms))), (((extra legs))), mutated hands, (fused fingers), (too many fingers), (((long neck))), Photoshop, videogame, ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, mutation, mutated, extra limbs, extra legs, extra arms, disfigured deformed cross-eye, ((body out of )), blurry, bad art, bad anatomy, 3d render, two faces, duplicate, coppy, multi, two, disfigured, kitsch, ugly, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, disfigured, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long neck, long body, ugly, disgusting, poorly drawn, childish, mutilated, mangled, old ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, extra limbs, disfigured, deformed, body out of frame, blurry, bad anatomy, blurred, watermark, grainy, signature, cut off, draf, blurry, bad anatomy, extra limbs, poorly drawn face, poorly drawn hands, missing fingers"
negative2 = "ugly, deformed, noisy, blurry, distorted, out of focus, bad anatomy, extra limbs, poorly drawn face, poorly drawn hands, missing fingers"
Expand Down
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ py -3.11 -m venv .wvenv
python -m pip install uv
python -m uv pip install -r requirements.txt

# Deployment with GitHub Actions

This repository includes a workflow that builds Docker images for **RunPod**
and **Google Cloud Run**. Dependencies are installed with `uv pip` and the
workflow caches build layers for faster rebuilds. The workflow can be found in
`.github/workflows/docker-build.yml`. See [docs/deployment.md](docs/deployment.md)
for details on how to use the images.

# contributing guidelines
Please help in any way.

Expand Down
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 120
exclude = .git,__pycache__,.venv,tests
9 changes: 9 additions & 0 deletions tests/test_health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_healthz():
response = client.get("/healthz")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
Loading