mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-07 13:11:30 +08:00
docs: Add quickstart guide and Docker deployment
This commit is contained in:
parent
0a697cde7f
commit
819d2a2490
339
docs/content/guides/docker.md
Normal file
339
docs/content/guides/docker.md
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
# Docker Deployment
|
||||||
|
|
||||||
|
Running Gunicorn in Docker containers is the most common deployment pattern
|
||||||
|
for modern Python applications. This guide covers best practices for
|
||||||
|
containerizing Gunicorn applications.
|
||||||
|
|
||||||
|
## Basic Dockerfile
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy application
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Run gunicorn
|
||||||
|
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Build and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t myapp .
|
||||||
|
docker run -p 8000:8000 myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Use environment variables for configuration:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Configuration via environment
|
||||||
|
ENV GUNICORN_WORKERS=4
|
||||||
|
ENV GUNICORN_BIND=0.0.0.0:8000
|
||||||
|
|
||||||
|
CMD gunicorn app:app \
|
||||||
|
--workers ${GUNICORN_WORKERS} \
|
||||||
|
--bind ${GUNICORN_BIND}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use `GUNICORN_CMD_ARGS`:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENV GUNICORN_CMD_ARGS="--workers=4 --bind=0.0.0.0:8000"
|
||||||
|
CMD ["gunicorn", "app:app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Worker Count
|
||||||
|
|
||||||
|
In containers, determine workers based on available CPU:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# gunicorn.conf.py
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
workers = multiprocessing.cpu_count() * 2 + 1
|
||||||
|
bind = "0.0.0.0:8000"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or let Kubernetes/Docker limit CPU and calculate accordingly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# At runtime
|
||||||
|
gunicorn app:app --workers $(( 2 * $(nproc) + 1 ))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Non-Root User
|
||||||
|
|
||||||
|
Run as a non-root user for security:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN useradd --create-home appuser
|
||||||
|
WORKDIR /home/appuser/app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY --chown=appuser:appuser . .
|
||||||
|
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Health Checks
|
||||||
|
|
||||||
|
Add a health check endpoint and Docker health check:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8000/health || exit 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multi-Stage Build
|
||||||
|
|
||||||
|
Reduce image size with multi-stage builds:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Build stage
|
||||||
|
FROM python:3.12 AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
|
||||||
|
|
||||||
|
# Runtime stage
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy wheels and install
|
||||||
|
COPY --from=builder /wheels /wheels
|
||||||
|
RUN pip install --no-cache-dir /wheels/* && rm -rf /wheels
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "4"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
Example `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgres://db:5432/myapp
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 512M
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=myapp
|
||||||
|
- POSTGRES_PASSWORD=secret
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
```
|
||||||
|
|
||||||
|
## Kubernetes Deployment
|
||||||
|
|
||||||
|
Example Kubernetes deployment:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myapp
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: myapp
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: myapp
|
||||||
|
image: myapp:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
env:
|
||||||
|
- name: GUNICORN_WORKERS
|
||||||
|
value: "4"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: "512Mi"
|
||||||
|
requests:
|
||||||
|
cpu: "500m"
|
||||||
|
memory: "256Mi"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8000
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8000
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myapp
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: myapp
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Graceful Shutdown
|
||||||
|
|
||||||
|
Gunicorn handles `SIGTERM` gracefully by default. Configure the timeout:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
CMD ["gunicorn", "app:app", \
|
||||||
|
"--bind", "0.0.0.0:8000", \
|
||||||
|
"--graceful-timeout", "30", \
|
||||||
|
"--timeout", "120"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Match Docker's stop timeout:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
stop_grace_period: 30s
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
Log to stdout/stderr for Docker log collection:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# gunicorn.conf.py
|
||||||
|
accesslog = "-"
|
||||||
|
errorlog = "-"
|
||||||
|
loglevel = "info"
|
||||||
|
```
|
||||||
|
|
||||||
|
Use JSON logging for log aggregation:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# gunicorn.conf.py
|
||||||
|
import json
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class JsonFormatter:
|
||||||
|
def format(self, record):
|
||||||
|
return json.dumps({
|
||||||
|
"timestamp": datetime.datetime.utcnow().isoformat(),
|
||||||
|
"level": record.levelname,
|
||||||
|
"message": record.getMessage(),
|
||||||
|
})
|
||||||
|
|
||||||
|
logconfig_dict = {
|
||||||
|
"version": 1,
|
||||||
|
"formatters": {
|
||||||
|
"json": {"()": JsonFormatter}
|
||||||
|
},
|
||||||
|
"handlers": {
|
||||||
|
"console": {
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"formatter": "json",
|
||||||
|
"stream": "ext://sys.stdout"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"handlers": ["console"],
|
||||||
|
"level": "INFO"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Worker Timeout
|
||||||
|
|
||||||
|
If workers are killed with `[CRITICAL] WORKER TIMEOUT`, increase the timeout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --timeout 120
|
||||||
|
```
|
||||||
|
|
||||||
|
Or investigate slow requests in your application.
|
||||||
|
|
||||||
|
### Out of Memory
|
||||||
|
|
||||||
|
If containers are OOM-killed:
|
||||||
|
|
||||||
|
1. Reduce worker count
|
||||||
|
2. Use `--max-requests` to restart workers periodically
|
||||||
|
3. Increase container memory limits
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --workers 2 --max-requests 1000 --max-requests-jitter 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection Reset
|
||||||
|
|
||||||
|
If you see connection resets, ensure:
|
||||||
|
|
||||||
|
1. Load balancer health checks match your `/health` endpoint
|
||||||
|
2. Graceful timeout is sufficient for in-flight requests
|
||||||
|
3. Keepalive settings match between Gunicorn and upstream proxy
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Deploy](../deploy.md) - General deployment patterns
|
||||||
|
- [Settings](../reference/settings.md) - All configuration options
|
||||||
@ -3,140 +3,174 @@
|
|||||||
!!! note
|
!!! note
|
||||||
Gunicorn requires **Python 3.12 or newer**.
|
Gunicorn requires **Python 3.12 or newer**.
|
||||||
|
|
||||||
|
## Quick Install
|
||||||
|
|
||||||
|
=== "pip"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "pipx"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pipx install gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Docker"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -p 8000:8000 -v $(pwd):/app -w /app \
|
||||||
|
python:3.12-slim sh -c "pip install gunicorn && gunicorn app:app"
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Docker guide](guides/docker.md) for production configurations.
|
||||||
|
|
||||||
|
=== "System Packages"
|
||||||
|
|
||||||
|
**Debian/Ubuntu:**
|
||||||
|
```bash
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fedora:**
|
||||||
|
```bash
|
||||||
|
sudo dnf install python3-gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
**Arch Linux:**
|
||||||
|
```bash
|
||||||
|
sudo pacman -S gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
System packages may lag behind the latest release. For production,
|
||||||
|
prefer pip installation in a virtual environment.
|
||||||
|
|
||||||
|
## Virtual Environment (Recommended)
|
||||||
|
|
||||||
|
Always install Gunicorn inside a virtual environment to isolate dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Create virtual environment
|
||||||
|
python -m venv venv
|
||||||
|
|
||||||
|
# Activate it
|
||||||
|
source venv/bin/activate # Linux/macOS
|
||||||
|
# or: venv\Scripts\activate # Windows
|
||||||
|
|
||||||
|
# Install gunicorn
|
||||||
pip install gunicorn
|
pip install gunicorn
|
||||||
```
|
```
|
||||||
|
|
||||||
## From source
|
## From Source
|
||||||
|
|
||||||
Install Gunicorn from GitHub if you want the latest development version:
|
Install the latest development version from GitHub:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install git+https://github.com/benoitc/gunicorn.git
|
pip install git+https://github.com/benoitc/gunicorn.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Stay current by upgrading in place:
|
Upgrade to the latest commit:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install -U git+https://github.com/benoitc/gunicorn.git
|
pip install -U git+https://github.com/benoitc/gunicorn.git
|
||||||
```
|
```
|
||||||
|
|
||||||
## Async workers
|
## Extra Packages
|
||||||
|
|
||||||
Install Eventlet or Gevent if your application benefits from cooperative I/O.
|
Gunicorn provides optional extras for additional worker types and features.
|
||||||
Both rely on `greenlet`, so make sure the Python headers are available (for
|
Install them with pip's bracket syntax:
|
||||||
example, install the `python-dev` package on Ubuntu).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install greenlet # Required for both
|
|
||||||
pip install eventlet # For eventlet workers
|
|
||||||
pip install gunicorn[eventlet] # Or, using extra
|
|
||||||
pip install gevent # For gevent workers
|
|
||||||
pip install gunicorn[gevent] # Or, using extra
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
Gevent also needs `libevent` 1.4.x or 2.0.4+. Install it from your package
|
|
||||||
manager or build it manually if the packaged version is too old.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Extra packages
|
|
||||||
|
|
||||||
Some Gunicorn options require additional dependencies. Install them via
|
|
||||||
extras to pull everything in with one command.
|
|
||||||
|
|
||||||
Most extras enable alternative worker types—see the
|
|
||||||
[design docs](design.md) for when each worker makes sense.
|
|
||||||
|
|
||||||
- `gunicorn[eventlet]` — Eventlet-based greenlet workers
|
|
||||||
- `gunicorn[gevent]` — Gevent-based greenlet workers
|
|
||||||
- `gunicorn[gthread]` — Threaded workers
|
|
||||||
- `gunicorn[tornado]` — Tornado-based workers (not recommended)
|
|
||||||
|
|
||||||
If you run more than one Gunicorn instance, the
|
|
||||||
[`proc_name`](reference/settings.md#proc_name) setting helps distinguish them in tools such
|
|
||||||
as `ps` and `top`.
|
|
||||||
|
|
||||||
- `gunicorn[setproctitle]` — Enables setting the process name
|
|
||||||
|
|
||||||
You can combine multiple extras, for example:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install gunicorn[gevent,setproctitle]
|
pip install gunicorn[gevent,setproctitle]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Debian GNU/Linux
|
### Worker Types
|
||||||
|
|
||||||
On Debian systems prefer the distribution packages unless you need per-project
|
| Extra | Description |
|
||||||
virtual environments:
|
|-------|-------------|
|
||||||
|
| `gunicorn[eventlet]` | Eventlet-based greenlet workers |
|
||||||
|
| `gunicorn[gevent]` | Gevent-based greenlet workers |
|
||||||
|
| `gunicorn[gthread]` | Threaded workers |
|
||||||
|
| `gunicorn[tornado]` | Tornado-based workers (not recommended) |
|
||||||
|
|
||||||
- Zero-effort installation: automatically starts multiple instances based on
|
See the [design docs](design.md) for guidance on choosing worker types.
|
||||||
configs in `/etc/gunicorn.d`.
|
|
||||||
- Sensible log locations (`/var/log/gunicorn`) with `logrotate` support.
|
|
||||||
- Improved security: run each instance with a dedicated UNIX user/group.
|
|
||||||
- Safe upgrades: minimal downtime, reversible changes, and easy package purge.
|
|
||||||
|
|
||||||
### stable ("buster")
|
### Utilities
|
||||||
|
|
||||||
The Debian [stable](https://www.debian.org/releases/stable/) release ships
|
| Extra | Description |
|
||||||
Gunicorn 19.9.0 (December 2020):
|
|-------|-------------|
|
||||||
|
| `gunicorn[setproctitle]` | Set process name in `ps`/`top` output |
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
If running multiple Gunicorn instances, use `setproctitle` with the
|
||||||
|
[`proc_name`](reference/settings.md#proc_name) setting to distinguish them.
|
||||||
|
|
||||||
|
## Async Workers
|
||||||
|
|
||||||
|
For applications using async I/O patterns, install the appropriate greenlet
|
||||||
|
library:
|
||||||
|
|
||||||
|
=== "Gevent"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install gunicorn[gevent]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --worker-class gevent
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Eventlet"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install gunicorn[eventlet]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --worker-class eventlet
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "ASGI (asyncio)"
|
||||||
|
|
||||||
|
No extra installation required:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --worker-class asgi
|
||||||
|
```
|
||||||
|
|
||||||
|
For better performance, install uvloop:
|
||||||
|
```bash
|
||||||
|
pip install uvloop
|
||||||
|
gunicorn app:app --worker-class asgi --asgi-loop uvloop
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Greenlet-based workers require the Python development headers. On Ubuntu:
|
||||||
|
`sudo apt-get install python3-dev`
|
||||||
|
|
||||||
|
## Verify Installation
|
||||||
|
|
||||||
|
Check the installed version:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install gunicorn3
|
gunicorn --version
|
||||||
```
|
```
|
||||||
|
|
||||||
Install Gunicorn 20.0.4 from [Debian Backports](https://backports.debian.org/)
|
Test with a simple application:
|
||||||
by adding this line to `/etc/apt/sources.list`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
deb http://ftp.debian.org/debian buster-backports main
|
|
||||||
```
|
|
||||||
|
|
||||||
Refresh package metadata and install:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get update
|
echo 'def app(e, s): s("200 OK", []); return [b"OK"]' > test_app.py
|
||||||
sudo apt-get -t buster-backports install gunicorn
|
gunicorn test_app:app
|
||||||
|
# Visit http://127.0.0.1:8000
|
||||||
```
|
```
|
||||||
|
|
||||||
### oldstable ("stretch")
|
## Next Steps
|
||||||
|
|
||||||
Stretch provides Gunicorn 19.6.0 (December 2020). Install the Python 3 version:
|
- [Quickstart](quickstart.md) - Get running in 5 minutes
|
||||||
|
- [Run](run.md) - CLI usage and framework integration
|
||||||
```bash
|
- [Configure](configure.md) - Configuration options
|
||||||
sudo apt-get install gunicorn3
|
|
||||||
```
|
|
||||||
|
|
||||||
To upgrade to 19.7.1 from backports, add:
|
|
||||||
|
|
||||||
```text
|
|
||||||
deb http://ftp.debian.org/debian stretch-backports main
|
|
||||||
```
|
|
||||||
|
|
||||||
Then update and install:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -t stretch-backports install gunicorn3
|
|
||||||
```
|
|
||||||
|
|
||||||
### testing ("bullseye") and unstable ("sid")
|
|
||||||
|
|
||||||
Both distributions include Gunicorn 20.0.4. Install it in the usual way:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt-get install gunicorn
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ubuntu
|
|
||||||
|
|
||||||
Ubuntu 20.04 LTS (Focal Fossa) and newer include Gunicorn 20.0.4. Keep it
|
|
||||||
current through the package manager:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install gunicorn
|
|
||||||
```
|
|
||||||
|
|||||||
115
docs/content/quickstart.md
Normal file
115
docs/content/quickstart.md
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# Quickstart
|
||||||
|
|
||||||
|
Get a Python web application running with Gunicorn in 5 minutes.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create an Application
|
||||||
|
|
||||||
|
Create `app.py`:
|
||||||
|
|
||||||
|
=== "Flask"
|
||||||
|
|
||||||
|
```python
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def hello():
|
||||||
|
return "Hello, World!"
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "FastAPI"
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def hello():
|
||||||
|
return {"message": "Hello, World!"}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Django"
|
||||||
|
|
||||||
|
Django projects already have a WSGI application at `myproject/wsgi.py`.
|
||||||
|
No additional code is needed.
|
||||||
|
|
||||||
|
=== "Plain WSGI"
|
||||||
|
|
||||||
|
```python
|
||||||
|
def app(environ, start_response):
|
||||||
|
data = b"Hello, World!"
|
||||||
|
start_response("200 OK", [
|
||||||
|
("Content-Type", "text/plain"),
|
||||||
|
("Content-Length", str(len(data)))
|
||||||
|
])
|
||||||
|
return [data]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app
|
||||||
|
```
|
||||||
|
|
||||||
|
For Django:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn myproject.wsgi
|
||||||
|
```
|
||||||
|
|
||||||
|
For FastAPI (ASGI):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --worker-class asgi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add Workers
|
||||||
|
|
||||||
|
Use multiple workers to handle concurrent requests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --workers 4
|
||||||
|
```
|
||||||
|
|
||||||
|
A good starting point is `2 * CPU_CORES + 1` workers.
|
||||||
|
|
||||||
|
## Bind to a Port
|
||||||
|
|
||||||
|
By default Gunicorn binds to `127.0.0.1:8000`. Change it with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app --bind 0.0.0.0:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration File
|
||||||
|
|
||||||
|
Create `gunicorn.conf.py` for reusable settings:
|
||||||
|
|
||||||
|
```python
|
||||||
|
bind = "0.0.0.0:8000"
|
||||||
|
workers = 4
|
||||||
|
accesslog = "-"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunicorn app:app
|
||||||
|
```
|
||||||
|
|
||||||
|
Gunicorn automatically loads `gunicorn.conf.py` from the current directory.
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- [Run](run.md) - Full CLI reference and framework integration
|
||||||
|
- [Configure](configure.md) - Configuration file options
|
||||||
|
- [Deploy](deploy.md) - Production deployment with nginx and process managers
|
||||||
|
- [Settings](reference/settings.md) - Complete settings reference
|
||||||
10
mkdocs.yml
10
mkdocs.yml
@ -7,19 +7,23 @@ use_directory_urls: true
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
- Guides:
|
- Getting Started:
|
||||||
|
- Quickstart: quickstart.md
|
||||||
- Install: install.md
|
- Install: install.md
|
||||||
- Run: run.md
|
- Run: run.md
|
||||||
- Configure: configure.md
|
- Configure: configure.md
|
||||||
|
- Guides:
|
||||||
- Deploy: deploy.md
|
- Deploy: deploy.md
|
||||||
|
- Docker: guides/docker.md
|
||||||
- ASGI Worker: asgi.md
|
- ASGI Worker: asgi.md
|
||||||
- uWSGI Protocol: uwsgi.md
|
- uWSGI Protocol: uwsgi.md
|
||||||
- Signals: signals.md
|
- Signals: signals.md
|
||||||
- Instrumentation: instrumentation.md
|
- Instrumentation: instrumentation.md
|
||||||
- Custom: custom.md
|
- Custom: custom.md
|
||||||
- Community: community.md
|
|
||||||
- FAQ: faq.md
|
|
||||||
- Design: design.md
|
- Design: design.md
|
||||||
|
- Community:
|
||||||
|
- Overview: community.md
|
||||||
|
- FAQ: faq.md
|
||||||
- Reference:
|
- Reference:
|
||||||
- Settings: reference/settings.md
|
- Settings: reference/settings.md
|
||||||
- News:
|
- News:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user