diff --git a/.envs/.production.example/.api b/.envs/.production.example/.api index e889488f..158c4754 100644 --- a/.envs/.production.example/.api +++ b/.envs/.production.example/.api @@ -1,6 +1,5 @@ # API (Django) # ------------------------------------------------------------------------------ -DATABASE_HOST=db SECRET_KEY=verysecure ALLOWED_HOSTS=yourdomain.tld,www.yourdomain.tdl DATABASE_PASSWORD=alsoverysecure diff --git a/api/Dockerfile b/api/Dockerfile index 1a4d06dc..9a8bc75b 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -6,7 +6,6 @@ ENV HOME=/home/mysagw ENV PYTHONUNBUFFERED=1 ENV DJANGO_SETTINGS_MODULE mysagw.settings ENV APP_HOME=/app -ENV UWSGI_INI /app/uwsgi.ini RUN mkdir -p /app \ && useradd -u 901 -r mysagw --create-home \ @@ -31,4 +30,9 @@ COPY . $APP_HOME EXPOSE 8000 -CMD /bin/sh -c "wait-for-it $DATABASE_HOST:${DATABASE_PORT:-5432} -- poetry run ./manage.py migrate && poetry run uwsgi" +CMD [\ + "/bin/sh", "-c", \ + "wait-for-it $DATABASE_HOST:${DATABASE_PORT:-5432} -- \ + poetry run ./manage.py migrate && \ + exec poetry run gunicorn --workers 10 --access-logfile - --limit-request-line 16384 --bind 0.0.0.0:8000 mysagw.wsgi" \ +] diff --git a/api/mysagw/wsgi.py b/api/mysagw/wsgi.py index c0eb9b1e..7d25e6e3 100644 --- a/api/mysagw/wsgi.py +++ b/api/mysagw/wsgi.py @@ -1,5 +1,5 @@ """ -WSGI config for project_app2 project. +WSGI config for mySAGW project. It exposes the WSGI callable as a module-level variable named ``application``. diff --git a/api/poetry.lock b/api/poetry.lock index 9f9b453c..e0d22526 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "arrow" @@ -820,6 +820,27 @@ sh = [ [package.extras] trusted-deps = ["arrow (==1.2.3)", "click (==8.1.3)", "sh (==1.14.3)"] +[[package]] +name = "gunicorn" +version = "22.0.0" +description = "WSGI HTTP Server for UNIX" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gunicorn-22.0.0-py3-none-any.whl", hash = "sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9"}, + {file = "gunicorn-22.0.0.tar.gz", hash = "sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +eventlet = ["eventlet (>=0.24.1,!=0.36.0)"] +gevent = ["gevent (>=1.4.0)"] +setproctitle = ["setproctitle"] +testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"] +tornado = ["tornado (>=0.2)"] + [[package]] name = "identify" version = "2.5.35" @@ -1811,16 +1832,6 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] -[[package]] -name = "uwsgi" -version = "2.0.24" -description = "The uWSGI server" -optional = false -python-versions = "*" -files = [ - {file = "uwsgi-2.0.24.tar.gz", hash = "sha256:77b6dd5cd633f4ae87ee393f7701f617736815499407376e78f3d16467523afe"}, -] - [[package]] name = "virtualenv" version = "20.25.1" @@ -1876,4 +1887,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "1672ddf918c2a25902469ab79aee81fb5acde729a9b4993a97230cbf5096bb76" +content-hash = "ebe07979e03c84e6af2d43e223cfa03786296a52861191e96d6a764ec16ee4b9" diff --git a/api/pyproject.toml b/api/pyproject.toml index b676bdf5..d13a9e1f 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -22,6 +22,7 @@ django-watchman = "^1.3.0" djangorestframework = "^3.15.2" djangorestframework-jsonapi = "^6.0.0" drf-extra-fields = "^3.5.0" +gunicorn = "^22.0.0" mozilla-django-oidc = "^3.0.0" openpyxl = "3.0.10" # TODO: dependency of `pyexcel-xlsx`. Remove as soon as https://github.com/pyexcel/pyexcel-xlsx/issues/52 is resolved psycopg2-binary = "^2.9.6" @@ -30,7 +31,6 @@ pyexcel-xlsx = "^0.6.0" pypdf = "^4.1.0" requests = "^2.32.2" reportlab = "^4.1.0" -uwsgi = "^2.0.24" [tool.poetry.group.dev.dependencies] django-extensions = "^3.2.3" diff --git a/api/uwsgi.ini b/api/uwsgi.ini deleted file mode 100644 index 7a580e3b..00000000 --- a/api/uwsgi.ini +++ /dev/null @@ -1,71 +0,0 @@ -# These settings can be overridden by environment-variables: https://git.io/JemA2 -[uwsgi] -http = 0.0.0.0:8000 - -# Crash if there are any unknown configuration parameters in the ini file. -strict = true - -# Path to wsgi.py -wsgi-file = /app/mysagw/wsgi.py - -# Enable graceful shutdown of workers (built-in prefork+threading multi-worker -# management mode) -master = true - -# By default threads are disabled. This can cause issues if your application -# uses background threads. Without setting this parameter to true, your -# threads will not run. -enable-threads = true - -# Delete temporary file (sockets, pidfiles, ...) during shutdown -vacuum = true - -# Disable single interpreter since certain C extenions can not cope with it. -# Since we don't run multiple applications on the same workers we can safely -# disable this. -single-interpreter = true - -# By default SIGTERM will brutally reload uWSGI instead of shuting it down. With -# this option enabled SIGTERM shuts down uWSGI as everybody would expect. -die-on-term = true - -# Let uWSGI crash if it is not able to load the application module. -need-app = true - -# uWSGI's logging is rather verbose. Instead of logging every request (which -# already happens on the reverse proxy level), logging all 4xx and 5xx errors -# should suffice. -disable-logging = true -log-4xx = true -log-5xx = true - -# It is a good idea to recycle workers every now and then to prevent memory -# leaks or unintentional states. -max-requests = 1000 ; Restart workers after this many requests -max-worker-lifetime = 3600 ; Restart workers after this many seconds -reload-on-rss = 2048 ; Restart workers after this much resident memory -worker-reload-mercy = 60 ; How long to wait before forcefully killing workers - -# The busyness algorithm attempts to always have spare workers available, -# which is useful when anticipating unexpected traffic surges. -cheaper-algo = busyness -processes = 500 ; Maximum number of workers allowed -cheaper = 8 ; Minimum number of workers allowed -cheaper-initial = 16 ; Workers created at startup -cheaper-overload = 1 ; Length of a cycle in seconds -cheaper-step = 16 ; How many workers to spawn at a time - -cheaper-busyness-multiplier = 30 ; How many cycles to wait before killing workers -cheaper-busyness-min = 20 ; Below this threshold, kill workers (if stable for multiplier cycles) -cheaper-busyness-max = 70 ; Above this threshold, spawn new workers -cheaper-busyness-backlog-alert = 16 ; Spawn emergency workers if more than this many requests are waiting in the queue -cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue - -# SIGKILL workers after certain timeout if they get stuck. -harakiri = 60 - -# Auto rename worker processes -auto-procname = true -procname-prefix = "mySAGW-API " ; note the space - -buffer-size = 16384 diff --git a/docker-compose.yml b/docker-compose.yml index f5a7c4b5..b4c6f40f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,9 @@ services: api: image: adfinis-sygroup/mysagw + environment: + - DATABASE_HOST=db + - DATABASE_PORT=5432 depends_on: - db