Deploying FastAPI with Docker

A
Author
13 May, 2026 1 min read 1.22K views

A production FastAPI deployment is usually a container running an ASGI server behind a reverse proxy or load balancer.

Dockerfile

FROM python:3.13-slim

# uv for fast, reproducible installs
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

COPY . .

RUN useradd --create-home appuser
USER appuser

EXPOSE 8000
CMD ["uv", "run", "--no-sync", "fastapi", "run", "app/main.py", "--port", "8000", "--proxy-headers"]

Copying the dependency files before the source code lets Docker cache the install layer, so rebuilds after code changes are fast.

Workers

  • In Kubernetes or similar, run one process per container and scale the number of containers.
  • On a single VM, run multiple worker processes: fastapi run --workers 4 (or uvicorn app.main:app --workers 4).
  • A typical starting point is one worker per CPU core; measure and adjust.

Health checks

@app.get("/healthz")
async def health():
    return {"ok": True}

@app.get("/readyz")
async def ready(db: DbSession):
    await db.execute(text("SELECT 1"))   # fails if the DB is unreachable
    return {"ok": True}

Behind a proxy

--proxy-headers makes the app trust X-Forwarded-For and X-Forwarded-Proto, so client IPs and HTTPS redirects are correct. Only enable it when the app really sits behind a trusted proxy.

Production checklist

  • Configuration from environment variables (pydantic-settings works well).
  • Structured JSON logs to stdout.
  • Run database migrations as a separate step before starting new containers.
  • Disable or protect /docs if your API is private: FastAPI(docs_url=None).
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.