uvicorn settings
This commit is contained in:
@@ -24,6 +24,7 @@ Load these references only when needed:
|
||||
|
||||
- FastAPI patterns and app structure: [./references/fastapi-best-practices.md](./references/fastapi-best-practices.md)
|
||||
- uv project layout and dependency management: [./references/uv-project-layout.md](./references/uv-project-layout.md)
|
||||
- uvicorn CLI settings reference: [./references/uvicorn-settings.md](./references/uvicorn-settings.md)
|
||||
- Docker and cloud-native patterns: [./references/docker-cloud-native.md](./references/docker-cloud-native.md)
|
||||
|
||||
---
|
||||
@@ -45,6 +46,7 @@ Before making changes, map the current state across six areas. Produce a short g
|
||||
|
||||
Load [./references/fastapi-best-practices.md](./references/fastapi-best-practices.md) for structure rules.
|
||||
Load [./references/uv-project-layout.md](./references/uv-project-layout.md) for uv migration rules.
|
||||
Load [./references/uvicorn-settings.md](./references/uvicorn-settings.md) for uvicorn CLI reference.
|
||||
|
||||
Completion check: You can name every gap before touching any file.
|
||||
|
||||
@@ -209,28 +211,58 @@ Completion check: `uv run uvicorn my_app.main:app --reload` starts with no impor
|
||||
|
||||
### Step 4: uvicorn Production Configuration
|
||||
|
||||
**Never** configure uvicorn inside application code. Pass all settings via CLI or environment.
|
||||
Load [./references/uvicorn-settings.md](./references/uvicorn-settings.md) for the full settings reference.
|
||||
|
||||
**Never** configure uvicorn inside application code. Pass all settings via CLI or environment variables (`UVICORN_*` prefix).
|
||||
|
||||
```bash
|
||||
# Development
|
||||
uv run uvicorn my_app.main:app --reload --host 127.0.0.1 --port 8000
|
||||
# Development — reload only; never in production
|
||||
uv run uvicorn my_app.main:app \
|
||||
--reload \
|
||||
--host 127.0.0.1 \
|
||||
--port 8000 \
|
||||
--log-level debug
|
||||
|
||||
# Production (single process — let orchestrator handle replication)
|
||||
# Production — single process (orchestrator handles replication)
|
||||
uv run uvicorn my_app.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8000 \
|
||||
--workers 1 \
|
||||
--loop uvloop \
|
||||
--http h11 \
|
||||
--loop auto \
|
||||
--http auto \
|
||||
--log-level info \
|
||||
--access-log \
|
||||
--proxy-headers \
|
||||
--forwarded-allow-ips '*'
|
||||
--forwarded-allow-ips '*' \
|
||||
--timeout-graceful-shutdown 30
|
||||
```
|
||||
|
||||
**When to use `--workers > 1`:** Only for single-server Docker Compose deployments where you cannot replicate at the orchestrator level. For Kubernetes / cloud run: always `--workers 1` and scale via replicas.
|
||||
**Key flags for production:**
|
||||
|
||||
**`--proxy-headers`** is required whenever the container sits behind a reverse proxy (nginx, traefik, cloud load balancer) — it makes FastAPI trust `X-Forwarded-For` and `X-Forwarded-Proto`.
|
||||
| Flag | Value | Reason |
|
||||
|------|-------|--------|
|
||||
| `--host 0.0.0.0` | Required in containers | Bind to all interfaces, not just loopback |
|
||||
| `--workers 1` | Kubernetes/Cloud Run | Orchestrator replicates containers |
|
||||
| `--loop auto` | Default | Uses `uvloop` when available (install `uvicorn[standard]`) |
|
||||
| `--http auto` | Default | Uses `httptools` when available |
|
||||
| `--proxy-headers` | Behind any proxy | Trusts `X-Forwarded-For`, `X-Forwarded-Proto` |
|
||||
| `--forwarded-allow-ips '*'` | Container/K8s | Trusts proxy headers from all IPs (safe when inside a trusted network) |
|
||||
| `--timeout-graceful-shutdown 30` | Prod | Seconds to wait before force-closing requests on shutdown |
|
||||
| `--no-access-log` | High-traffic prod | Disable per-request logs if using structured app-level logging |
|
||||
|
||||
**Environment variable equivalents** (useful in `docker-compose.yml` / K8s manifests):
|
||||
|
||||
```bash
|
||||
UVICORN_HOST=0.0.0.0
|
||||
UVICORN_PORT=8000
|
||||
UVICORN_WORKERS=1
|
||||
UVICORN_LOG_LEVEL=info
|
||||
UVICORN_PROXY_HEADERS=true
|
||||
UVICORN_FORWARDED_ALLOW_IPS=*
|
||||
```
|
||||
|
||||
**`--reload` and `--workers` are mutually exclusive** — never combine them.
|
||||
|
||||
**When to use `--workers > 1`:** Only for Docker Compose on a single host where orchestrator-level replication is not available. For Kubernetes / Cloud Run / Fargate: always `--workers 1` and scale via replicas — this gives predictable per-container memory and cleaner crash isolation.
|
||||
|
||||
Completion check: `curl http://localhost:8000/healthz` returns `{"status":"ok"}`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Docker and Cloud-Native Patterns
|
||||
|
||||
Source: https://docs.docker.com/build/building/best-practices/ | https://docs.astral.sh/uv/guides/integration/docker/ | https://fastapi.tiangolo.com/deployment/docker/
|
||||
Source: https://docs.docker.com/build/building/best-practices/ | https://docs.astral.sh/uv/guides/integration/docker/ | https://fastapi.tiangolo.com/deployment/docker/ | https://uvicorn.dev/deployment/
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# uvicorn Settings Reference
|
||||
|
||||
Source: https://uvicorn.dev/settings/ | https://uvicorn.dev/deployment/
|
||||
|
||||
---
|
||||
|
||||
## Configuration Methods
|
||||
|
||||
Three equivalent approaches (CLI takes precedence over env vars):
|
||||
|
||||
```bash
|
||||
# 1. CLI flags
|
||||
uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
|
||||
# 2. UVICORN_* environment variables
|
||||
export UVICORN_HOST=0.0.0.0
|
||||
export UVICORN_PORT=8000
|
||||
uvicorn main:app
|
||||
|
||||
# 3. Programmatic (dev/test only)
|
||||
uvicorn.run("main:app", host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
**Note:** `UVICORN_*` env vars cannot be used from within an `--env-file`. The `--env-file` flag is for the ASGI *application's* config, not uvicorn's own config.
|
||||
|
||||
---
|
||||
|
||||
## All Settings by Category
|
||||
|
||||
### Socket Binding
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--host <str>` | `127.0.0.1` | Use `0.0.0.0` in containers to bind all interfaces |
|
||||
| `--port <int>` | `8000` | Use `0` to auto-pick an available port |
|
||||
| `--uds <path>` | — | UNIX domain socket path (use behind Nginx) |
|
||||
| `--fd <int>` | — | Inherit socket from file descriptor (use with Supervisor) |
|
||||
|
||||
### Production
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--workers <int>` | `1` (or `$WEB_CONCURRENCY`) | **Mutually exclusive with `--reload`** |
|
||||
| `--env-file <path>` | — | Env file for the *application* (not uvicorn itself) |
|
||||
| `--timeout-worker-healthcheck <int>` | `5` | Seconds before killing a stuck worker |
|
||||
|
||||
### Logging
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--log-level <str>` | `info` | `critical`, `error`, `warning`, `info`, `debug`, `trace` |
|
||||
| `--log-config <path>` | — | `.json` or `.yaml` for `dictConfig()`; other formats use `fileConfig()` |
|
||||
| `--no-access-log` | — | Disable access log without changing log level |
|
||||
| `--use-colors / --no-use-colors` | auto | Force color on/off in log output |
|
||||
|
||||
### Implementation
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--loop <str>` | `auto` | `auto`, `asyncio`, `uvloop`. `uvloop` requires `uvicorn[standard]` |
|
||||
| `--http <str>` | `auto` | `auto`, `h11`, `httptools`. `httptools` requires `uvicorn[standard]` |
|
||||
| `--ws <str>` | `auto` | `auto`, `none`, `websockets`, `websockets-sansio`, `wsproto` |
|
||||
| `--lifespan <str>` | `auto` | `auto`, `on`, `off` |
|
||||
| `--ws-max-size <int>` | `16777216` | WebSocket max message size in bytes (16 MB) |
|
||||
| `--ws-ping-interval <float>` | `20.0` | WebSocket ping interval in seconds |
|
||||
| `--ws-ping-timeout <float>` | `20.0` | WebSocket ping timeout in seconds |
|
||||
|
||||
### HTTP / Proxy Headers
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--proxy-headers` | enabled | Trust `X-Forwarded-For`, `X-Forwarded-Proto` from trusted IPs |
|
||||
| `--no-proxy-headers` | — | Disable proxy header trust entirely |
|
||||
| `--forwarded-allow-ips <list>` | `127.0.0.1` | Comma-separated IPs/networks/literals to trust. Use `'*'` to trust all (safe in containers behind a trusted LB). **Security risk if exposed directly to internet.** |
|
||||
| `--root-path <str>` | `""` | ASGI `root_path` for apps mounted below a URL prefix |
|
||||
| `--server-header / --no-server-header` | enabled | Include/suppress `Server` response header |
|
||||
| `--date-header / --no-date-header` | enabled | Include/suppress `Date` response header |
|
||||
| `--header <name:value>` | — | Add custom default response headers (repeatable) |
|
||||
|
||||
### Resource Limits
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--limit-concurrency <int>` | — | Max concurrent connections/tasks; returns HTTP 503 above this |
|
||||
| `--limit-max-requests <int>` | — | Restart worker after N requests (limits memory leak accumulation) |
|
||||
| `--limit-max-requests-jitter <int>` | `0` | Random jitter added to `--limit-max-requests` to stagger worker restarts |
|
||||
| `--backlog <int>` | `2048` | Max queued connections under high load |
|
||||
|
||||
### Timeouts
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--timeout-keep-alive <int>` | `5` | Close keep-alive connections after N seconds of inactivity |
|
||||
| `--timeout-graceful-shutdown <int>` | — | Seconds to wait for in-flight requests to complete on SIGTERM before force-closing |
|
||||
|
||||
### Development
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--reload` | `False` | Auto-reload on file changes. **Never use in production.** Mutually exclusive with `--workers`. |
|
||||
| `--reload-dir <path>` | `.` | Directory to watch for changes (repeatable) |
|
||||
| `--reload-delay <float>` | `0.25` | Seconds between reload checks |
|
||||
| `--reload-include <glob>` | `*.py` | Patterns to include in watch (requires `watchfiles`) |
|
||||
| `--reload-exclude <glob>` | `.*, .py[cod], ...` | Patterns to exclude from watch (requires `watchfiles`) |
|
||||
|
||||
### Application
|
||||
|
||||
| Flag | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `--factory` | — | Treat `APP` as a `() -> ASGI app` callable (app factory pattern) |
|
||||
| `--app-dir <path>` | `.` | Add to `PYTHONPATH` when resolving `APP` |
|
||||
| `--reset-contextvars` | `False` | Run each request in a fresh `contextvars.Context` (asyncio only; workaround for a CPython context-leak bug) |
|
||||
|
||||
---
|
||||
|
||||
## Recommended Production CMD
|
||||
|
||||
```bash
|
||||
uvicorn my_app.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8000 \
|
||||
--workers 1 \
|
||||
--loop auto \
|
||||
--http auto \
|
||||
--log-level info \
|
||||
--proxy-headers \
|
||||
--forwarded-allow-ips '*' \
|
||||
--timeout-graceful-shutdown 30
|
||||
```
|
||||
|
||||
In a Dockerfile (exec form):
|
||||
|
||||
```dockerfile
|
||||
CMD ["uvicorn", "my_app.main:app",
|
||||
"--host", "0.0.0.0",
|
||||
"--port", "8000",
|
||||
"--workers", "1",
|
||||
"--proxy-headers",
|
||||
"--forwarded-allow-ips", "*",
|
||||
"--timeout-graceful-shutdown", "30"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Process Manager Options
|
||||
|
||||
### Built-in multi-worker (Docker Compose / single host)
|
||||
|
||||
```bash
|
||||
uvicorn my_app.main:app --workers 4
|
||||
```
|
||||
|
||||
The built-in manager spawns workers, monitors their health, and auto-restarts crashed workers. Signal support:
|
||||
- `SIGHUP` — rolling graceful restart (deploy new code without dropping requests)
|
||||
- `SIGTTIN` — add one worker
|
||||
- `SIGTTOU` — remove one worker
|
||||
|
||||
### Behind Nginx (UNIX socket)
|
||||
|
||||
```bash
|
||||
uvicorn my_app.main:app --uds /tmp/uvicorn.sock --proxy-headers
|
||||
```
|
||||
|
||||
Nginx config headers to set:
|
||||
```nginx
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `uvicorn[standard]` vs bare `uvicorn`
|
||||
|
||||
| Package | Extras included |
|
||||
|---------|----------------|
|
||||
| `uvicorn` | Pure Python h11 HTTP, asyncio event loop |
|
||||
| `uvicorn[standard]` | `uvloop` (faster event loop), `httptools` (faster HTTP parser), `watchfiles` (better reload), `websockets`, `PyYAML` (for `--log-config`) |
|
||||
|
||||
Use `uvicorn[standard]` in all environments. The `[standard]` extras are also included when you install `fastapi[standard]`.
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
| Anti-pattern | Fix |
|
||||
|---|---|
|
||||
| `--reload` in Dockerfile CMD | Remove it — `--reload` is dev-only |
|
||||
| `--loop uvloop` explicitly | Use `--loop auto` — it selects uvloop automatically when available |
|
||||
| `--http h11` explicitly in prod | Use `--http auto` — it selects httptools when available |
|
||||
| `uvicorn.run()` at module level (no `if __name__ == '__main__':`) | Breaks multiprocessing workers; always guard it |
|
||||
| Shell form `CMD uvicorn ...` | Exec form `CMD ["uvicorn", ...]` — required for SIGTERM to reach uvicorn |
|
||||
Reference in New Issue
Block a user