diff --git a/Dockerfile-prod b/Dockerfile-prod new file mode 100644 index 0000000..4da059a --- /dev/null +++ b/Dockerfile-prod @@ -0,0 +1,14 @@ +FROM python:3.13 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +WORKDIR /edrop + +RUN apt-get update && apt-get install -y supervisor && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY edrop-gunicorn.sh /edrop/edrop-gunicorn.sh +COPY supervisor.service /etc/systemd/system/supervisor.service +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] diff --git a/README.md b/README.md index efa5c57..093759d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ To run this Django app, the easiest is to run it via Docker. - Make sure Docker is installed. - Make sure there is a folder `data/db` in this folder (if it's the first time you run this project, you will need to create `db` inside `data`). -- Then from this directory, run `docker compose up` +- To run the dev server from this directory, run `docker compose up` +- To run the production server from this directory, run `docker compose -f docker-compose-prod.yml up` - The app will be available at http://localhost:8000/. ## Developing the App diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml new file mode 100644 index 0000000..683ee7e --- /dev/null +++ b/docker-compose-prod.yml @@ -0,0 +1,33 @@ +version: "3.9" + +services: + db: + image: postgres:16 + platform: linux/amd64 + volumes: + - ./data/db:/var/lib/postgresql/data + environment: + - POSTGRES_DB=postgres + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + ports: + - "5432:5432" + web: + build: + context: . + dockerfile: Dockerfile-prod + platform: linux/amd64 + volumes: + - .:/edrop + - ./data/files:/data/files + ports: + - "8000:8000" + environment: + - POSTGRES_NAME=postgres + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - DATA_PATH=/data/files/ + - MEDIA_URL_PATH=/dashboard/files/ + - MEDIA_ROOT_PATH=files + depends_on: + - db \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f452a88..4afcb70 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.9" services: db: - image: postgres + image: postgres:16 platform: linux/amd64 volumes: - ./data/db:/var/lib/postgresql/data diff --git a/edrop-gunicorn.sh b/edrop-gunicorn.sh new file mode 100755 index 0000000..fe71f07 --- /dev/null +++ b/edrop-gunicorn.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +NAME="edrop" # Name of the application +DJANGODIR=/edrop # Django project directory +NUM_WORKERS=3 # Number of Gunicorn workers +DJANGO_SETTINGS_MODULE=edrop.settings # Django settings module +DJANGO_WSGI_MODULE=edrop.wsgi # WSGI module name + +echo "Starting $NAME as `whoami`" + +# Activate the virtual environment +cd $DJANGODIR +source .env_app +export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE +export PYTHONPATH=$DJANGODIR:$PYTHONPATH +mkdir -p /edrop/logs +python -m pip install -r requirements.txt +python manage.py migrate +python manage.py collectstatic --noinput + +# Start your Django Unicorn +# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon) +exec gunicorn ${DJANGO_WSGI_MODULE}:application \ + --name $NAME \ + --workers $NUM_WORKERS \ + --bind=0.0.0.0:8000 \ + --log-level=info \ + --log-file /edrop/logs/edrop_supervisor.log \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 3477b37..92c7f7f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ django==5.1 +gunicorn==22.0.0 psycopg2==2.9.10 dj-static==0.0.6 \ No newline at end of file diff --git a/supervisor.service b/supervisor.service new file mode 100644 index 0000000..9150edc --- /dev/null +++ b/supervisor.service @@ -0,0 +1,14 @@ +# /etc/systemd/system/supervisor.service + +[Unit] +Description=Supervisor +After=syslog.target network.target + +[Service] +ExecStart=/usr/bin/supervisord --configuration=/etc/supervisor/conf.d/supervisord.conf --logfile=/edrop/logs/edrop_supervisor.log +ExecStop=/usr/bin/supervisorctl shutdown +ExecReload=/usr/bin/supervisorctl reload all +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/supervisord.conf b/supervisord.conf new file mode 100644 index 0000000..2bb497f --- /dev/null +++ b/supervisord.conf @@ -0,0 +1,24 @@ +[supervisord] +nodaemon=true + +[program:edrop] +command=/edrop/edrop-gunicorn.sh +directory=/edrop +autostart=true +autorestart=true +stdout_logfile=/edrop/logs/edrop_supervisor.log +stderr_logfile=/edrop/logs/edrop_supervisor.log +environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 + +; Need to wait for currently executing tasks to finish at shutdown. +; Increase this if you have very long running tasks. +stopwaitsecs = 600 + +; When resorting to send SIGKILL to the program to terminate it +; send SIGKILL to its whole process group instead, +; taking care of its children as well. +killasgroup=true + +; if rabbitmq is supervised, set its priority higher +; so it starts first +priority=998