Tune gunicorn/Postgres/Redis for a memory-limited server
- gunicorn: 3 workers -> 2 (this workload isn't CPU-bound per DEPLOYMENT.md's own sizing), add --preload so workers share immutable memory via copy-on-write instead of each independently importing Django, add --max-requests so a worker that renders a WeasyPrint invoice doesn't carry that memory forever. - Postgres: trim shared_buffers/max_connections from the image defaults (128MB/100), sized for a ~0.2GB dataset instead. - Redis: cap with --maxmemory as a ceiling, not a saving.
This commit is contained in:
11
Dockerfile
11
Dockerfile
@@ -91,10 +91,19 @@ EXPOSE 8000
|
||||
# Migrations are NOT run here. With more than one app container they would race, and a failed
|
||||
# migration inside a starting web process is a bad place to find out — deploy runs them once,
|
||||
# explicitly (see DEPLOYMENT.md).
|
||||
# 2 workers, not 3: DEPLOYMENT.md's own sizing says this workload isn't CPU-bound, and each
|
||||
# worker duplicates a full Django process — the single biggest lever on a memory-limited box.
|
||||
# --preload imports the app once in the master and forks workers via copy-on-write instead of
|
||||
# each re-importing Django independently (safe here: no app's ready() touches DB/Redis eagerly,
|
||||
# checked club/features/news/events). --max-requests recycles a worker periodically so the one
|
||||
# that happens to render a WeasyPrint invoice doesn't carry that +50-100MB forever.
|
||||
CMD ["gunicorn", "rosterchief.wsgi:application", \
|
||||
"--bind", "0.0.0.0:8000", \
|
||||
"--workers", "3", \
|
||||
"--workers", "2", \
|
||||
"--threads", "4", \
|
||||
"--preload", \
|
||||
"--max-requests", "500", \
|
||||
"--max-requests-jitter", "50", \
|
||||
"--timeout", "60", \
|
||||
"--access-logfile", "-", \
|
||||
"--error-logfile", "-"]
|
||||
|
||||
Reference in New Issue
Block a user