Deploying FastAPI with Docker
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(oruvicorn 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
/docsif 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.