Deploy a Python / FastAPI app

A FastAPI service on a live HTTPS URL, with a tiny Dockerfile you can copy as-is.

For Python the most reliable, reproducible path is a five-line Dockerfile — it pins exactly how the app installs and starts, so it deploys the same way every time. This recipe is the whole path.

In a hurry? Start from the ready-made fastapi-starter template — click Use this template on GitHub, then deploy it. Or follow the steps below to set up a project you already have.

1. Bind uvicorn to the assigned port

A standard FastAPI entrypoint in main.py:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"status": "ok"}

List your dependencies in requirements.txt:

fastapi
uvicorn[standard]

Your app must listen on 0.0.0.0 and read its port from the PORT environment variable — never localhost, never a hardcoded port. Dockhold assigns PORT at runtime; an app that ignores it can't receive traffic.

2. Add a minimal Dockerfile

Put this Dockerfile at the repo root:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Shell form so $PORT is expanded at runtime
CMD uvicorn main:app --host 0.0.0.0 --port $PORT

A Dockerfile at the repo root takes priority and tells Dockhold exactly how to build and run the app — no guesswork. The CMD is in shell form on purpose: that's what lets $PORT expand at runtime.

3. Read config and secrets from the environment

Set plain config in the dashboard and secrets in the Vault, then read them with os.environ:

import os
api_key = os.environ["SOME_API_KEY"]

4. Add a database (optional)

Enable the managed Postgres add-on and Dockhold injects DATABASE_URL. Read it with os.environ["DATABASE_URL"] — don't run your own database, and remember the filesystem is wiped on every restart, so persist state in the database, not on disk.

5. Connect the repo and deploy

  1. Push the project (with the Dockerfile) to a GitHub repository.
  2. Open the dashboard, connect GitHub, and pick the repo.
  3. Dockhold builds from your Dockerfile and runs it.

Your app goes live at https://<your-app>.dockhold.app with HTTPS handled for you. Every later push to your main branch redeploys.

Troubleshooting

  • URL times out: the CMD must use --host 0.0.0.0 --port $PORT and be in shell form (no [ ] brackets), or $PORT won't expand.
  • App not found / import error: main:app means a variable named app in main.py. Match the file and variable names to your project.
  • Missing dependency at runtime: add it to requirements.txt — only what's listed there is installed.

Next