Switch from uwsgi to gunicorn

This commit is contained in:
Gabriel Augendre 2022-11-10 17:42:05 +01:00
parent c43c33f06f
commit cf6df4bf2f
5 changed files with 36 additions and 83 deletions

View file

@ -93,38 +93,13 @@ ENV PATH /app/venv/bin:$PATH
ENV STATIC_ROOT=/app/static ENV STATIC_ROOT=/app/static
COPY --chown=django:django --from=venv $STATIC_ROOT $STATIC_ROOT COPY --chown=django:django --from=venv $STATIC_ROOT $STATIC_ROOT
# uWSGI env vars
##############################################
ENV UWSGI_HTTP=:8000
ENV UWSGI_CHDIR="/app/src"
ENV UWSGI_WSGI_FILE="/app/src/charasheet/wsgi.py"
ENV UWSGI_MASTER=1
ENV UWSGI_HTTP_AUTO_CHUNKED=1
ENV UWSGI_HTTP_KEEPALIVE=1
ENV UWSGI_UID=1000
ENV UWSGI_GID=1000
ENV UWSGI_WSGI_ENV_BEHAVIOR=holy
ENV UWSGI_DIE_ON_TERM=true
ENV UWSGI_STRICT=true
ENV UWSGI_NEED_APP=true
# Tweak for perf
ENV UWSGI_SINGLE_INTERPRETER=true
ENV UWSGI_AUTO_PROCNAME=true
ENV UWSGI_MAX_REQUESTS=5000
ENV UWSGI_MAX_WORKER_LIFETIME=3600
ENV UWSGI_RELOAD_ON_RSS=500
ENV UWSGI_WORKER_RELOAD_MERCY=10
ENV UWSGI_WORKERS=2 UWSGI_THREADS=4
# Create directory structure # Create directory structure
############################################## ##############################################
WORKDIR /app WORKDIR /app
COPY pyproject.toml poetry.lock ./ COPY pyproject.toml poetry.lock ./
ADD --chown=django:django ./src ./src ADD --chown=django:django ./src ./src
ADD --chown=django:django ./docker ./docker
COPY --chown=django:django tasks.py ./tasks.py COPY --chown=django:django tasks.py ./tasks.py
COPY --chown=django:django docker/uwsgi.ini ./uwsgi.ini
RUN mkdir -p /app/data /app/db RUN mkdir -p /app/data /app/db
@ -138,5 +113,7 @@ EXPOSE 8000
WORKDIR /app/src WORKDIR /app/src
HEALTHCHECK --start-period=30s CMD python -c "import requests; requests.get('http://localhost:8000', timeout=2)"
USER django USER django
CMD ["uwsgi", "--show-config", "--ini", "/app/uwsgi.ini"] CMD ["/app/docker/run.sh"]

4
docker/run.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
set -eux
python manage.py migrate --noinput
gunicorn blog.wsgi -b 0.0.0.0:8000 --log-file -

View file

@ -1,15 +0,0 @@
[uwsgi]
plugin = /app/escape_json_plugin.so
static-map = /media=/app/data/media/
logger-req = stdio
; json_uri and json_host are json-escaped fields defined in `escape_json_plugin.so`
log-format = "address":"%(addr)", "host":"%(json_host)", "method":"%(method)", "uri":"%(json_uri)", "protocol":"%(proto)", "resp_size":%(size), "req_body_size":%(cl), "resp_status":%(status), "resp_time":%(msecs), "referer":"%(referer)", "user_agent":"%(uagent)"
log-req-encoder = format {"source":"uwsgi-req", "time":"${strftime:%%FT%%T%%z}", ${msg}}
log-req-encoder = nl
; Ignore write errors
; https://github.com/getsentry/raven-python/issues/732#issuecomment-176854438
ignore-sigpipe = true
ignore-write-errors = true
disable-write-exception = true

66
poetry.lock generated
View file

@ -37,7 +37,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]] [[package]]
name = "beautifulsoup4" name = "beautifulsoup4"
@ -125,7 +125,7 @@ optional = false
python-versions = ">=3.6.0" python-versions = ">=3.6.0"
[package.extras] [package.extras]
unicode-backport = ["unicodedata2"] unicode_backport = ["unicodedata2"]
[[package]] [[package]]
name = "colorama" name = "colorama"
@ -218,7 +218,7 @@ django = ">=2.0"
requests = ">=2.4.3" requests = ">=2.4.3"
[package.extras] [package.extras]
amazon-ses = ["boto3"] amazon_ses = ["boto3"]
dev = ["flake8", "sphinx", "sphinx-rtd-theme", "tox", "twine", "wheel"] dev = ["flake8", "sphinx", "sphinx-rtd-theme", "tox", "twine", "wheel"]
postal = ["cryptography"] postal = ["cryptography"]
@ -365,7 +365,21 @@ optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
[package.extras] [package.extras]
docs = ["Sphinx"] docs = ["sphinx"]
[[package]]
name = "gunicorn"
version = "20.1.0"
description = "WSGI HTTP Server for UNIX"
category = "main"
optional = false
python-versions = ">=3.5"
[package.extras]
eventlet = ["eventlet (>=0.24.1)"]
gevent = ["gevent (>=1.4.0)"]
setproctitle = ["setproctitle"]
tornado = ["tornado (>=0.2)"]
[[package]] [[package]]
name = "h11" name = "h11"
@ -480,9 +494,6 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
[package.dependencies]
setuptools = "*"
[[package]] [[package]]
name = "outcome" name = "outcome"
version = "1.2.0" version = "1.2.0"
@ -689,7 +700,7 @@ pytest = ">=5.4.0"
[package.extras] [package.extras]
docs = ["sphinx", "sphinx-rtd-theme"] docs = ["sphinx", "sphinx-rtd-theme"]
testing = ["Django", "django-configurations (>=2.0)"] testing = ["django", "django-configurations (>=2.0)"]
[[package]] [[package]]
name = "pytest-html" name = "pytest-html"
@ -774,7 +785,7 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras] [package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
[[package]] [[package]]
name = "requests-toolbelt" name = "requests-toolbelt"
@ -801,19 +812,6 @@ trio = ">=0.17,<1.0"
trio-websocket = ">=0.9,<1.0" trio-websocket = ">=0.9,<1.0"
urllib3 = {version = ">=1.26,<2.0", extras = ["socks"]} urllib3 = {version = ">=1.26,<2.0", extras = ["socks"]}
[[package]]
name = "setuptools"
version = "65.5.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]] [[package]]
name = "six" name = "six"
version = "1.16.0" version = "1.16.0"
@ -925,14 +923,6 @@ brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "uwsgi"
version = "2.0.21"
description = "The uWSGI server"
category = "main"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.16.6" version = "20.16.6"
@ -967,7 +957,7 @@ optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[package.extras] [package.extras]
brotli = ["Brotli"] brotli = ["brotli"]
[[package]] [[package]]
name = "wsproto" name = "wsproto"
@ -983,7 +973,7 @@ h11 = ">=0.9.0,<1"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.10.0, <4" python-versions = ">=3.10.0, <4"
content-hash = "cd49a04260ba22d4bbe1ba66bf7ed229d16b22c91d6ab7d25e24fe73ac307be9" content-hash = "a8492fca0c4d83c2605cfd4e6aa9f043ba5969bd497ab20876ee1f93f2520d1f"
[metadata.files] [metadata.files]
ansicon = [ ansicon = [
@ -1321,6 +1311,10 @@ greenlet = [
{file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"}, {file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"},
{file = "greenlet-1.1.3.post0.tar.gz", hash = "sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c"}, {file = "greenlet-1.1.3.post0.tar.gz", hash = "sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c"},
] ]
gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
{file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
]
h11 = [ h11 = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
@ -1387,7 +1381,6 @@ pre-commit = [
] ]
prettytable = [ prettytable = [
{file = "prettytable-3.5.0-py3-none-any.whl", hash = "sha256:fe391c3b545800028edf5dbb6a5360893feb398367fcc1cf8d7a5b29ce5c59a1"}, {file = "prettytable-3.5.0-py3-none-any.whl", hash = "sha256:fe391c3b545800028edf5dbb6a5360893feb398367fcc1cf8d7a5b29ce5c59a1"},
{file = "prettytable-3.5.0.tar.gz", hash = "sha256:52f682ba4efe29dccb38ff0fe5bac8a23007d0780ff92a8b85af64bc4fc74d72"},
] ]
psycopg2-binary = [ psycopg2-binary = [
{file = "psycopg2-binary-2.9.5.tar.gz", hash = "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c"}, {file = "psycopg2-binary-2.9.5.tar.gz", hash = "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c"},
@ -1570,10 +1563,6 @@ requests-toolbelt = [
selenium = [ selenium = [
{file = "selenium-4.5.0-py3-none-any.whl", hash = "sha256:a733dd77d3171b846893f4d51b18967d809313f547a10974e26579f9ce797462"}, {file = "selenium-4.5.0-py3-none-any.whl", hash = "sha256:a733dd77d3171b846893f4d51b18967d809313f547a10974e26579f9ce797462"},
] ]
setuptools = [
{file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"},
{file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"},
]
six = [ six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
@ -1618,9 +1607,6 @@ urllib3 = [
{file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
] ]
uwsgi = [
{file = "uwsgi-2.0.21.tar.gz", hash = "sha256:35a30d83791329429bc04fe44183ce4ab512fcf6968070a7bfba42fc5a0552a9"},
]
virtualenv = [ virtualenv = [
{file = "virtualenv-20.16.6-py3-none-any.whl", hash = "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108"}, {file = "virtualenv-20.16.6-py3-none-any.whl", hash = "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108"},
{file = "virtualenv-20.16.6.tar.gz", hash = "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e"}, {file = "virtualenv-20.16.6.tar.gz", hash = "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e"},

View file

@ -17,12 +17,13 @@ django-linear-migrations = ">=2.2.0"
django-extensions = ">=3.1.5" django-extensions = ">=3.1.5"
psycopg2-binary = ">=2.8" psycopg2-binary = ">=2.8"
whitenoise = ">=6.2" whitenoise = ">=6.2"
uWSGI = ">=2.0.21"
selenium = ">=4.5.0" selenium = ">=4.5.0"
Markdown = ">=3.2" Markdown = ">=3.2"
django-registration = ">=3.3" django-registration = ">=3.3"
django-anymail = {extras = ["mailgun"], version = ">=8.6"} django-anymail = {extras = ["mailgun"], version = ">=8.6"}
django-bootstrap5 = ">=22.1" django-bootstrap5 = ">=22.1"
requests = ">=2.28.1"
gunicorn = "^20.1.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
django-debug-toolbar = ">=3.2" django-debug-toolbar = ">=3.2"