Deployment Guide¶
This guide covers deploying HawkAPI applications to production using Docker.
Quick Start¶
Copy the template files into your project:
Build and run:
Your app is now available at http://localhost:8000.
Dockerfile Walkthrough¶
The template uses a multi-stage build for minimal image size:
- Builder stage — installs
uv, resolves dependencies, copies source. - Runtime stage — copies only the virtualenv and source. No build tools in the final image.
Key features:
- Non-root user (
app) — prevents privilege escalation. - Layer caching —
pyproject.tomlis copied before source, so dependency install is cached unless deps change. - Health check — uses HawkAPI's built-in
/healthzendpoint.
Choosing a Server¶
Uvicorn (default)¶
Install: pip install hawkapi[uvicorn]
Granian (Rust-based, faster)¶
CMD ["granian", "--interface", "asgi", "--host", "0.0.0.0", "--port", "8000", "--workers", "4", "src.app:app"]
Install: pip install hawkapi[granian]
Worker Count¶
Rule of thumb: 2 × CPU cores + 1.
| CPU Cores | Workers |
|---|---|
| 1 | 3 |
| 2 | 5 |
| 4 | 9 |
| 8 | 17 |
For I/O-bound apps (database queries, external APIs), you can increase this. For CPU-bound apps, stay closer to core count.
Environment Variables¶
Use hawkapi.config.Settings to manage environment variables:
from hawkapi import Settings, env_field
class AppSettings(Settings):
database_url: str = env_field("DATABASE_URL")
redis_url: str = env_field("REDIS_URL", default="redis://localhost:6379/0")
debug: bool = env_field("DEBUG", default=False)
Pass variables via docker-compose.yml or -e flags.
Health Checks¶
HawkAPI auto-registers a /healthz endpoint (configurable via health_url):
The Dockerfile HEALTHCHECK uses this endpoint. Docker and orchestrators (Kubernetes, ECS) use health checks for restart decisions.
Graceful Shutdown¶
HawkAPI supports lifespan hooks for graceful startup and shutdown:
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app):
# Startup: open connections
db = await create_db_pool()
yield
# Shutdown: close connections
await db.close()
app = HawkAPI(lifespan=lifespan)
Docker sends SIGTERM on stop. Uvicorn/Granian handle this and trigger the shutdown hook.
Production Tips¶
- Read-only filesystem — mount source as read-only where possible.
- Resource limits — set memory and CPU limits in docker-compose or your orchestrator.
- Logging — use
StructuredLoggingMiddlewarefor JSON logs compatible with log aggregators. - Metrics — use
PrometheusMiddlewarefor monitoring with Grafana/Prometheus. - TLS — terminate TLS at a reverse proxy (nginx, Caddy, cloud load balancer), not in the app.
- uvloop — install
hawkapi[uvloop]for faster event loop (Linux only).