diff --git a/Dockerfile b/Dockerfile index 28bb3af64..25230c346 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,7 +56,5 @@ RUN if [ $STATIC_BUILD = "TRUE" ] ; \ then SECRET_KEY=dummy_value uv run python manage.py distill-local build --traceback --force ; \ fi -CMD ["gunicorn", "--preload", "-b", "0.0.0.0:8000", \ - "pydis_site.wsgi:application", "-w", "2", "--statsd-host", \ - "graphite.default.svc.cluster.local:8125", "--statsd-prefix", "site", \ - "--config", "file:gunicorn.conf.py"] +CMD ["waitress-serve", "--listen", "*:8000", \ + "--max-request-body-size=52428800", "pydis_site.wsgi:application"] diff --git a/gunicorn.conf.py b/gunicorn.conf.py deleted file mode 100644 index 4930ae5b8..000000000 --- a/gunicorn.conf.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -Configuration file for gunicorn. - -Code taken from https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn -""" -from prometheus_client import multiprocess - - -def child_exit(server, worker) -> None: - multiprocess.mark_process_dead(worker.pid) diff --git a/manage.py b/manage.py index 38bf6be0e..4b72320dd 100755 --- a/manage.py +++ b/manage.py @@ -31,7 +31,7 @@ class SiteManager: Manages the preparation and serving of the website for local use. This class is used solely for setting up the development - environment. In production, gunicorn is invoked directly + environment. In production, the WSGI server is invoked directly and migrations are handled in an init container. Usage: diff --git a/pydis_site/README.md b/pydis_site/README.md index 7faa1593b..1ef24d222 100644 --- a/pydis_site/README.md +++ b/pydis_site/README.md @@ -53,7 +53,7 @@ the website: determine _which URLs will lead to which Django views_. - [`wsgi.py`](./wsgi.py), which serves as an adapter for - [`gunicorn`](https://github.com/benoitc/gunicorn), + [`waitress`](https://github.com/Pylons/waitress), [`uwsgi`](https://github.com/unbit/uwsgi), or other application servers to run our application in production. Unless you want to test an interaction between our application and those servers, you probably won't need to touch this. diff --git a/pyproject.toml b/pyproject.toml index ba86b9cd8..ef4bf3dae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,6 @@ dependencies = [ "django-prometheus==2.4.1", "django-simple-bulma==2.6.0", "djangorestframework==3.16.0", - "gunicorn==24.1.1", "httpx==0.28.1", "markdown==3.8.2", "psycopg[binary]==3.2.9", @@ -22,6 +21,7 @@ dependencies = [ "python-frontmatter==1.1.0", "pyyaml==6.0.2", "sentry-sdk==2.33.0", + "waitress==3.0.2", "whitenoise==6.9.0", ] @@ -76,7 +76,6 @@ select = ["ANN", "B", "C4", "D", "DJ", "DTZ", "E", "F", "ISC", "INT", "N", "PGH" "pydis_site/apps/**/tests/test_*.py" = ["ANN", "D"] "static-builds/netlify_build.py" = ["T201"] "pydis_site/apps/api/tests/test_off_topic_channel_names.py" = ["RUF001"] -"gunicorn.conf.py" = ["ANN", "D"] "pydis_site/apps/api/models/bot/off_topic_channel_name.py" = ["RUF001"] [tool.taskipy.tasks] diff --git a/uv.lock b/uv.lock index 92f7b2e88..6ca425628 100644 --- a/uv.lock +++ b/uv.lock @@ -267,18 +267,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] -[[package]] -name = "gunicorn" -version = "24.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/0a/10739c03537ec5b131a867bf94df2e412b437696c7e5d26970e2198a80d2/gunicorn-24.1.1.tar.gz", hash = "sha256:f006d110e5cb3102859b4f5cd48335dbd9cc28d0d27cd24ddbdafa6c60929408", size = 287567, upload-time = "2026-01-24T01:15:31.359Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/90/cfe637677916fc6f53cd2b05d5746e249f683e1fa14c9e745a88c66f7290/gunicorn-24.1.1-py3-none-any.whl", hash = "sha256:757f6b621fc4f7581a90600b2cd9df593461f06a41d7259cb9b94499dc4095a8", size = 114920, upload-time = "2026-01-24T01:15:29.656Z" }, -] - [[package]] name = "h11" version = "0.16.0" @@ -374,15 +362,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, ] -[[package]] -name = "packaging" -version = "25.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, -] - [[package]] name = "platformdirs" version = "4.3.8" @@ -606,7 +585,6 @@ dependencies = [ { name = "django-prometheus" }, { name = "django-simple-bulma" }, { name = "djangorestframework" }, - { name = "gunicorn" }, { name = "httpx" }, { name = "markdown" }, { name = "psycopg", extra = ["binary"] }, @@ -615,6 +593,7 @@ dependencies = [ { name = "python-frontmatter" }, { name = "pyyaml" }, { name = "sentry-sdk" }, + { name = "waitress" }, { name = "whitenoise" }, ] @@ -640,7 +619,6 @@ requires-dist = [ { name = "django-prometheus", specifier = "==2.4.1" }, { name = "django-simple-bulma", specifier = "==2.6.0" }, { name = "djangorestframework", specifier = "==3.16.0" }, - { name = "gunicorn", specifier = "==24.1.1" }, { name = "httpx", specifier = "==0.28.1" }, { name = "markdown", specifier = "==3.8.2" }, { name = "psycopg", extras = ["binary"], specifier = "==3.2.9" }, @@ -649,6 +627,7 @@ requires-dist = [ { name = "python-frontmatter", specifier = "==1.1.0" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "sentry-sdk", specifier = "==2.33.0" }, + { name = "waitress", specifier = "==3.0.2" }, { name = "whitenoise", specifier = "==6.9.0" }, ] @@ -745,6 +724,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, ] +[[package]] +name = "waitress" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/cb/04ddb054f45faa306a230769e868c28b8065ea196891f09004ebace5b184/waitress-3.0.2.tar.gz", hash = "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f", size = 179901, upload-time = "2024-11-16T20:02:35.195Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/57/a27182528c90ef38d82b636a11f606b0cbb0e17588ed205435f8affe3368/waitress-3.0.2-py3-none-any.whl", hash = "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e", size = 56232, upload-time = "2024-11-16T20:02:33.858Z" }, +] + [[package]] name = "whitenoise" version = "6.9.0"