replace uwsgi with uvicorn

This commit is contained in:
Simon 2024-12-23 21:53:27 +07:00
parent e5e51f1a60
commit 7dcef45b97
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
9 changed files with 69 additions and 42 deletions

View File

@ -69,7 +69,7 @@ RUN sed -i 's/^user www\-data\;$/user root\;/' /etc/nginx/nginx.conf
# copy application into container # copy application into container
COPY ./backend /app COPY ./backend /app
COPY ./docker_assets/run.sh /app COPY ./docker_assets/run.sh /app
COPY ./docker_assets/uwsgi.ini /app COPY ./docker_assets/backend_start.py /app
COPY --from=node-builder ./frontend/dist /app/static COPY --from=node-builder ./frontend/dist /app/static

View File

@ -57,7 +57,7 @@ Take a look at the example [docker-compose.yml](https://github.com/tubearchivist
| REDIS_HOST | Hostname for Redis | Required | | REDIS_HOST | Hostname for Redis | Required |
| TZ | Set your timezone for the scheduler | Required | | TZ | Set your timezone for the scheduler | Required |
| TA_PORT | Overwrite Nginx port | Optional | | TA_PORT | Overwrite Nginx port | Optional |
| TA_UWSGI_PORT | Overwrite container internal uwsgi port | Optional | | TA_BACKEND_PORT | Overwrite container internal backend server port | Optional |
| TA_ENABLE_AUTH_PROXY | Enables support for forwarding auth in reverse proxies | [Read more](https://docs.tubearchivist.com/configuration/forward-auth/) | | TA_ENABLE_AUTH_PROXY | Enables support for forwarding auth in reverse proxies | [Read more](https://docs.tubearchivist.com/configuration/forward-auth/) |
| TA_AUTH_PROXY_USERNAME_HEADER | Header containing username to log in | Optional | | TA_AUTH_PROXY_USERNAME_HEADER | Header containing username to log in | Optional |
| TA_AUTH_PROXY_LOGOUT_URL | Logout URL for forwarded auth | Optional | | TA_AUTH_PROXY_LOGOUT_URL | Logout URL for forwarded auth | Optional |

View File

@ -27,7 +27,7 @@ class EnvironmentSettings:
ENABLE_CAST: bool = bool(environ.get("ENABLE_CAST")) ENABLE_CAST: bool = bool(environ.get("ENABLE_CAST"))
TZ: str = str(environ.get("TZ", "UTC")) TZ: str = str(environ.get("TZ", "UTC"))
TA_PORT: int = int(environ.get("TA_PORT", False)) TA_PORT: int = int(environ.get("TA_PORT", False))
TA_UWSGI_PORT: int = int(environ.get("TA_UWSGI_PORT", False)) TA_BACKEND_PORT: int = int(environ.get("TA_BACKEND_PORT", False))
TA_USERNAME: str = str(environ.get("TA_USERNAME")) TA_USERNAME: str = str(environ.get("TA_USERNAME"))
TA_PASSWORD: str = str(environ.get("TA_PASSWORD")) TA_PASSWORD: str = str(environ.get("TA_PASSWORD"))
@ -75,7 +75,7 @@ class EnvironmentSettings:
TZ: {self.TZ} TZ: {self.TZ}
ENABLE_CAST: {self.ENABLE_CAST} ENABLE_CAST: {self.ENABLE_CAST}
TA_PORT: {self.TA_PORT} TA_PORT: {self.TA_PORT}
TA_UWSGI_PORT: {self.TA_UWSGI_PORT} TA_BACKEND_PORT: {self.TA_BACKEND_PORT}
TA_USERNAME: {self.TA_USERNAME} TA_USERNAME: {self.TA_USERNAME}
TA_PASSWORD: *****""" TA_PASSWORD: *****"""
) )

View File

@ -8,6 +8,7 @@ Functionality:
import os import os
import re import re
from time import sleep
from common.src.env_settings import EnvironmentSettings from common.src.env_settings import EnvironmentSettings
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
@ -60,9 +61,11 @@ EXPECTED_ENV_VARS = [
"ES_URL", "ES_URL",
"TA_HOST", "TA_HOST",
] ]
UNEXPECTED_ENV_VARS = {
"TA_UWSGI_PORT": "Has been replaced with 'TA_BACKEND_PORT'"
}
INST = "https://github.com/tubearchivist/tubearchivist#installing-and-updating" INST = "https://github.com/tubearchivist/tubearchivist#installing-and-updating"
NGINX = "/etc/nginx/sites-available/default" NGINX = "/etc/nginx/sites-available/default"
UWSGI = "/app/uwsgi.ini"
class Command(BaseCommand): class Command(BaseCommand):
@ -76,9 +79,10 @@ class Command(BaseCommand):
self.stdout.write(LOGO) self.stdout.write(LOGO)
self.stdout.write(TOPIC) self.stdout.write(TOPIC)
self._expected_vars() self._expected_vars()
self._unexpected_vars()
self._elastic_user_overwrite() self._elastic_user_overwrite()
self._ta_port_overwrite() self._ta_port_overwrite()
self._ta_uwsgi_overwrite() self._ta_backend_port_overwrite()
self._enable_cast_overwrite() self._enable_cast_overwrite()
self._create_superuser() self._create_superuser()
@ -90,20 +94,41 @@ class Command(BaseCommand):
if not env.get(var): if not env.get(var):
message = f" 🗙 expected env var {var} not set\n {INST}" message = f" 🗙 expected env var {var} not set\n {INST}"
self.stdout.write(self.style.ERROR(message)) self.stdout.write(self.style.ERROR(message))
sleep(60)
raise CommandError(message) raise CommandError(message)
message = " ✓ all expected env vars are set" message = " ✓ all expected env vars are set"
self.stdout.write(self.style.SUCCESS(message)) self.stdout.write(self.style.SUCCESS(message))
def _unexpected_vars(self):
"""check for unexpected env vars"""
self.stdout.write("[2] checking for unexpected env vars")
for var, message in UNEXPECTED_ENV_VARS.items():
if not os.environ.get(var):
continue
message = (
f" 🗙 unexpected env var {var} found\n"
f" {message} \n"
" see release notes for a list of all changes."
)
self.stdout.write(self.style.ERROR(message))
sleep(60)
raise CommandError(message)
message = " ✓ no unexpected env vars found"
self.stdout.write(self.style.SUCCESS(message))
def _elastic_user_overwrite(self): def _elastic_user_overwrite(self):
"""check for ELASTIC_USER overwrite""" """check for ELASTIC_USER overwrite"""
self.stdout.write("[2] check ES user overwrite") self.stdout.write("[3] check ES user overwrite")
env = EnvironmentSettings.ES_USER env = EnvironmentSettings.ES_USER
self.stdout.write(self.style.SUCCESS(f" ✓ ES user is set to {env}")) self.stdout.write(self.style.SUCCESS(f" ✓ ES user is set to {env}"))
def _ta_port_overwrite(self): def _ta_port_overwrite(self):
"""set TA_PORT overwrite for nginx""" """set TA_PORT overwrite for nginx"""
self.stdout.write("[3] check TA_PORT overwrite") self.stdout.write("[4] check TA_PORT overwrite")
overwrite = EnvironmentSettings.TA_PORT overwrite = EnvironmentSettings.TA_PORT
if not overwrite: if not overwrite:
self.stdout.write(self.style.SUCCESS(" TA_PORT is not set")) self.stdout.write(self.style.SUCCESS(" TA_PORT is not set"))
@ -119,35 +144,30 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS(message)) self.stdout.write(self.style.SUCCESS(message))
def _ta_uwsgi_overwrite(self): def _ta_backend_port_overwrite(self):
"""set TA_UWSGI_PORT overwrite""" """set TA_BACKEND_PORT overwrite"""
self.stdout.write("[4] check TA_UWSGI_PORT overwrite") self.stdout.write("[5] check TA_BACKEND_PORT overwrite")
overwrite = EnvironmentSettings.TA_UWSGI_PORT overwrite = EnvironmentSettings.TA_BACKEND_PORT
if not overwrite: if not overwrite:
message = " TA_UWSGI_PORT is not set" message = " TA_BACKEND_PORT is not set"
self.stdout.write(self.style.SUCCESS(message)) self.stdout.write(self.style.SUCCESS(message))
return return
# nginx # modify nginx conf
regex = re.compile(r"uwsgi_pass localhost:[0-9]{1,5}") regex = re.compile(r"proxy_pass http://localhost:[0-9]{1,5}")
to_overwrite = f"uwsgi_pass localhost:{overwrite}" to_overwrite = f"proxy_pass http://localhost:{overwrite}"
changed = file_overwrite(NGINX, regex, to_overwrite) changed = file_overwrite(NGINX, regex, to_overwrite)
# uwsgi
regex = re.compile(r"socket = :[0-9]{1,5}")
to_overwrite = f"socket = :{overwrite}"
changed = file_overwrite(UWSGI, regex, to_overwrite)
if changed: if changed:
message = f" ✓ TA_UWSGI_PORT changed to {overwrite}" message = f" ✓ TA_BACKEND_PORT changed to {overwrite}"
else: else:
message = f" ✓ TA_UWSGI_PORT already set to {overwrite}" message = f" ✓ TA_BACKEND_PORT already set to {overwrite}"
self.stdout.write(self.style.SUCCESS(message)) self.stdout.write(self.style.SUCCESS(message))
def _enable_cast_overwrite(self): def _enable_cast_overwrite(self):
"""cast workaround, remove auth for static files in nginx""" """cast workaround, remove auth for static files in nginx"""
self.stdout.write("[5] check ENABLE_CAST overwrite") self.stdout.write("[6] check ENABLE_CAST overwrite")
overwrite = EnvironmentSettings.ENABLE_CAST overwrite = EnvironmentSettings.ENABLE_CAST
if not overwrite: if not overwrite:
self.stdout.write(self.style.SUCCESS(" ENABLE_CAST is not set")) self.stdout.write(self.style.SUCCESS(" ENABLE_CAST is not set"))
@ -164,7 +184,7 @@ class Command(BaseCommand):
def _create_superuser(self): def _create_superuser(self):
"""create superuser if not exist""" """create superuser if not exist"""
self.stdout.write("[6] create superuser") self.stdout.write("[7] create superuser")
is_created = Account.objects.filter(is_superuser=True) is_created = Account.objects.filter(is_superuser=True)
if is_created: if is_created:
message = " superuser already created" message = " superuser already created"

View File

@ -9,6 +9,6 @@ Pillow==11.0.0
redis==5.2.1 redis==5.2.1
requests==2.32.3 requests==2.32.3
ryd-client==0.0.6 ryd-client==0.0.6
uWSGI==2.0.28 uvicorn==0.34.0
whitenoise==6.8.2 whitenoise==6.8.2
yt-dlp[default]==2024.12.13 yt-dlp[default]==2024.12.13

18
docker_assets/backend_start.py Executable file
View File

@ -0,0 +1,18 @@
"""start backend python application, read env var"""
from os import environ
import uvicorn
LOG_LEVEL = "info" if environ.get("DJANGO_DEBUG") else "error"
PORT = int(environ.get("TA_BACKEND_PORT", 8080))
if __name__ == "__main__":
uvicorn.run(
"config.asgi:application",
host="0.0.0.0",
port=PORT,
workers=4,
log_level=LOG_LEVEL,
reload=False,
)

View File

@ -34,13 +34,13 @@ server {
} }
location /api { location /api {
include uwsgi_params; include proxy_params;
uwsgi_pass localhost:8080; proxy_pass http://localhost:8080;
} }
location /admin { location /admin {
include uwsgi_params; include proxy_params;
uwsgi_pass localhost:8080; proxy_pass http://localhost:8080;
} }
location /static/ { location /static/ {

View File

@ -20,4 +20,4 @@ nginx &
celery -A task.celery worker --loglevel=INFO --max-tasks-per-child 10 & celery -A task.celery worker --loglevel=INFO --max-tasks-per-child 10 &
celery -A task beat --loglevel=INFO \ celery -A task beat --loglevel=INFO \
--scheduler django_celery_beat.schedulers:DatabaseScheduler & --scheduler django_celery_beat.schedulers:DatabaseScheduler &
uwsgi --ini uwsgi.ini python backend_start.py

View File

@ -1,11 +0,0 @@
[uwsgi]
module = config.wsgi:application
master = True
pidfile = /tmp/project-master.pid
vacuum = True
max-requests = 5000
socket = :8080
buffer-size = 8192
log-5xx = true
log-4xx = true
disable-logging = true