From b057fedb5f1b0542ec3483d83cf5597c13f028d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 13:55:33 +0100 Subject: [PATCH 1/9] Add optional env variable DJANGO_FORCE_DEV_MODE to force production settings to dev mode for debugging --- .../shimatta_kenkyusho/settings_production.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shimatta_kenkyusho/shimatta_kenkyusho/settings_production.py b/shimatta_kenkyusho/shimatta_kenkyusho/settings_production.py index 901bdc1..2775540 100644 --- a/shimatta_kenkyusho/shimatta_kenkyusho/settings_production.py +++ b/shimatta_kenkyusho/shimatta_kenkyusho/settings_production.py @@ -16,9 +16,13 @@ The following environment variables have to be set: - DJANGO_MEDIA_URL - DJANGO_MEDIA_ROOT - DJANGO_POSTGRESQL_SOCKET +- DJANGO_POSTGRESQL_PORT The following can be set +- DJANGO_POSTGRESQL_PW (assumed empty if missing) +- DJANGO_POSTGRESQL_USER (assmumed empty if mssing) - DJANGO_SECURE_HSTS_SECONDS (defaults to 120) +- DJANGO_FORCE_DEV_MODE """ @@ -46,8 +50,11 @@ SECRET_KEY = get_env_value('DJANGO_SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False +if get_env_value('DJANGO_FORCE_DEV_MODE', default=False) == 'True': + DEBUG = True -ALLOWED_HOSTS = ['localhost', get_env_value('DJANGO_ALLOWED_HOST')] + +ALLOWED_HOSTS = ['127.0.0.1', 'localhost', get_env_value('DJANGO_ALLOWED_HOST')] # Application definition @@ -232,4 +239,4 @@ CSRF_COOKIE_SECURE = True SECURE_SSL_REDIRECT = False -SECURE_HSTS_SECONDS = get_env_value('DJANGO_SECURE_HSTS_SECONDS', default=120) \ No newline at end of file +SECURE_HSTS_SECONDS = get_env_value('DJANGO_SECURE_HSTS_SECONDS', default=120) From 64d0a1bfb3f341369a7e209b2b00cdc55629a98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 16:36:36 +0100 Subject: [PATCH 2/9] Make gunicorn listen to all incoming IPs on Port 8000. This is necessary to use a spearate net with the postgres container. --- entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint.sh b/entrypoint.sh index 42b543c..9295252 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,4 +3,4 @@ source /home/shimatta/kenkyusho/.venv/bin/activate cd /home/shimatta/kenkyusho/shimatta_kenkyusho python manage.py migrate --settings shimatta_kenkyusho.settings_production python manage.py collectstatic --settings shimatta_kenkyusho.settings_production --noinput -gunicorn -w 4 shimatta_kenkyusho.wsgi:application +gunicorn -w 4 --bind 0.0.0.0:8000 shimatta_kenkyusho.wsgi:application From d2ce635f05c9e85d06e40ddc092cee03632f2fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 16:37:23 +0100 Subject: [PATCH 3/9] Add compose setup * Use a dedicated postgresql container as database * Controlled via .env file * Ecample script for interactive container startup --- .env.example | 29 +++++++++++++++++++++++ .gitignore | 3 +++ compose.yaml | 36 +++++++++++++++++++++++++++++ start_docker_compose_interactive.sh | 7 ++++++ 4 files changed, 75 insertions(+) create mode 100644 .env.example create mode 100644 compose.yaml create mode 100755 start_docker_compose_interactive.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..169edd6 --- /dev/null +++ b/.env.example @@ -0,0 +1,29 @@ +#################################################################################################### +# Example configuration. Must be edited and copied to ".env" next to the compose.yaml +#################################################################################################### + + +# Path to to mount as the directory for static data. Must be served by a webserver on the /static path +DJANGO_STATIC_VOL=/path/to/static/root + +# Path to the media root. Must be served by a webserver on the media URL +DJANGO_MEDIA_VOL=/path/to/media/root + +# Port to serve the App +PORT=8000 + +# Secret Key. Must be edited before deployment +DJANGO_SECRET_KEY=534hj5jgh4365ghj35jgh245jgh24 + +# Allowed host be be accessed. Currently it is only possible to specify a single URL +DJANGO_ALLOWED_HOST=lab.example.com + +# Media URL for images and other content +DJANGO_MEDIA_URL=media.lab.example.com/ + +# DO NOT SET DEBUG MODE IN PRODUCTION +# DJANGO_FORCE_DEV_MODE=True + +# Set this password if you want to use a custom postgres password. The db should be condifed inside the docker network. +# Using the standard PW is therefore not a problem +# DJANGO_POSTGRESQL_PW=myfancynewpassword123donotsharemewithanyone \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6557b16..8c6eff1 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,6 @@ dmypy.json myenv/* + +run/* +.env diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..d273b48 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,36 @@ +services: + shimatta-kenkyusho-web: + build: . + volumes: + - "${DJANGO_STATIC_VOL:-./run/static}:/var/static" + - "${DJANGO_MEDIA_VOL:-./run/media}:/var/media" + environment: + DJANGO_POSTGRESQL_PW: "${DJANGO_POSTGRESQL_PW:-p4ssw0rd}" + DJANGO_POSTGRESQL_USER: "postgres" + DJANGO_SECRET_KEY: "${DJANGO_SECRET_KEY}" + DJANGO_ALLOWED_HOST: "${DJANGO_ALLOWED_HOST}" + DJANGO_STATIC_ROOT: "/var/static" + DJANGO_MEDIA_URL: "${DJANGO_MEDIA_URL}" + DJANGO_MEDIA_ROOT: "/var/media" + DJANGO_POSTGRESQL_SOCKET: "shimatta-kenkyusho-db" + DJANGO_POSTGRESQL_PORT: "5432" + DJANGO_FORCE_DEV_MODE: ${DJANGO_FORCE_DEV_MODE:-False} + ports: + - "${PORT}:8000" + networks: + - backendnet + depends_on: + - "shimatta-kenkyusho-db" + + shimatta-kenkyusho-db: + image: postgres:16.5-alpine + environment: + POSTGRES_PASSWORD: "${DJANGO_POSTGRESQL_PW:-p4ssw0rd}" + POSTGRES_DB: "shimatta_kenkyusho" + volumes: + - "${PGDATA:-./run/pgdata}:/var/lib/postgresql/data" + networks: + - backendnet + +networks: + backendnet: diff --git a/start_docker_compose_interactive.sh b/start_docker_compose_interactive.sh new file mode 100755 index 0000000..eaf2076 --- /dev/null +++ b/start_docker_compose_interactive.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Startup the db container +docker-compose start shimatta-kenkyusho-db + +# Override entrypoint to get interactive shell +docker-compose run --entrypoint="/bin/sh" -p 8000:8000 shimatta-kenkyusho-web \ No newline at end of file From fc5fa9f740a2cfb739b8af16299b2fb0b35c0708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 16:50:10 +0100 Subject: [PATCH 4/9] Fix startup issue with postgres on first start. Implement health check of postgres and delay django container until it's healthy. --- compose.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compose.yaml b/compose.yaml index d273b48..806ca0c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -20,7 +20,8 @@ services: networks: - backendnet depends_on: - - "shimatta-kenkyusho-db" + shimatta-kenkyusho-db: + condition: service_healthy shimatta-kenkyusho-db: image: postgres:16.5-alpine @@ -31,6 +32,11 @@ services: - "${PGDATA:-./run/pgdata}:/var/lib/postgresql/data" networks: - backendnet + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 networks: backendnet: From 144a65ee05b6c72aa2f5635b8d1a7b9a12d1580a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 16:52:18 +0100 Subject: [PATCH 5/9] Fix typo in eample env file --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 169edd6..e74875e 100644 --- a/.env.example +++ b/.env.example @@ -24,6 +24,6 @@ DJANGO_MEDIA_URL=media.lab.example.com/ # DO NOT SET DEBUG MODE IN PRODUCTION # DJANGO_FORCE_DEV_MODE=True -# Set this password if you want to use a custom postgres password. The db should be condifed inside the docker network. +# Set this password if you want to use a custom postgres password. The db should be confined inside the docker network. # Using the standard PW is therefore not a problem # DJANGO_POSTGRESQL_PW=myfancynewpassword123donotsharemewithanyone \ No newline at end of file From a59fad4866dfc3089b4545886044f3a3ea0338bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 17:33:45 +0100 Subject: [PATCH 6/9] Add self hosted entrypoint file for easier debugging which will use the integrated django server to serve all files --- entrypoint_self_hosted.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 entrypoint_self_hosted.sh diff --git a/entrypoint_self_hosted.sh b/entrypoint_self_hosted.sh new file mode 100755 index 0000000..e78916d --- /dev/null +++ b/entrypoint_self_hosted.sh @@ -0,0 +1,6 @@ +#!/bin/sh +source /home/shimatta/kenkyusho/.venv/bin/activate +cd /home/shimatta/kenkyusho/shimatta_kenkyusho +python manage.py migrate --settings shimatta_kenkyusho.settings_production + +python manage.py runserver 0.0.0.0:8000 --settings shimatta_kenkyusho.settings_production From 561b2aed2798e6a4ae33cd19166055e991fd174d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 19:10:28 +0100 Subject: [PATCH 7/9] Add the /healthcheck path which returns an HTTP200 OK response for checking the helath of the container after startup --- Dockerfile | 2 +- compose.yaml | 6 ++++++ shimatta_kenkyusho/parts/urls.py | 1 + shimatta_kenkyusho/parts/views.py | 12 +++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f9ba421..80c50d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM alpine:latest -RUN apk add --no-cache python3 py3-pip python3-dev py3-setuptools gcc python3-dev jpeg-dev zlib-dev musl-dev py3-gunicorn +RUN apk add --no-cache python3 py3-pip python3-dev py3-setuptools gcc python3-dev jpeg-dev zlib-dev musl-dev py3-gunicorn curl COPY . /home/shimatta/kenkyusho WORKDIR /home/shimatta/kenkyusho RUN python3 -m venv /home/shimatta/kenkyusho/.venv && . /home/shimatta/kenkyusho/.venv/bin/activate && pip install -r requirements.txt diff --git a/compose.yaml b/compose.yaml index 806ca0c..b9c9bb4 100644 --- a/compose.yaml +++ b/compose.yaml @@ -22,6 +22,12 @@ services: depends_on: shimatta-kenkyusho-db: condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f localhost:8000/healthcheck"] + interval: 5s + timeout: 5s + retries: 5 + start_period: 30s shimatta-kenkyusho-db: image: postgres:16.5-alpine diff --git a/shimatta_kenkyusho/parts/urls.py b/shimatta_kenkyusho/parts/urls.py index a693f79..8e9fd1b 100644 --- a/shimatta_kenkyusho/parts/urls.py +++ b/shimatta_kenkyusho/parts/urls.py @@ -16,4 +16,5 @@ urlpatterns = [ path('distributors//', parts_views.DistributorDetailView.as_view(), name='parts-distributors-detail'), path('manufacturers/', parts_views.ManufacturersViewSet.as_view(), name='parts-manufacturers'), path("manufacturers//", parts_views.ManufacturerDetailViewSet.as_view(), name='parts-manufacturers-detail'), + path("healthcheck/", parts_views.health_check_view, name='parts-health-check'), ] diff --git a/shimatta_kenkyusho/parts/views.py b/shimatta_kenkyusho/parts/views.py index 6de8672..64a4b57 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -18,8 +18,10 @@ from .forms import * from django.db.models import Q from django.db.models.functions import Lower from django.forms import formset_factory +from django.http import HttpResponse import uuid + ParameterSearchFormSet = formset_factory(ComponentParameterSearchForm, extra=1) class QrSearchForm(forms.Form): @@ -953,4 +955,12 @@ class ManufacturerDetailViewSet(LoginRequiredMixin, BaseTemplateMixin, DetailVie elif 'submit-manufacturer-edit' in request.POST: return self.edit_manufacturer(request) - return super().post(request, *args, **kwargs) \ No newline at end of file + return super().post(request, *args, **kwargs) + + +def health_check_view(request) -> HttpResponse: + """ + Health checking view. Returns empty http response with HTTP status OK. + This will be used to check + """ + return HttpResponse(status=200) \ No newline at end of file From 66f4eea77dd6074d368835a0cae9fd413f75c785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 19:36:27 +0100 Subject: [PATCH 8/9] Update env file example to contain Volume mount point for DB folder --- .env.example | 3 +++ compose.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index e74875e..ab72682 100644 --- a/.env.example +++ b/.env.example @@ -9,6 +9,9 @@ DJANGO_STATIC_VOL=/path/to/static/root # Path to the media root. Must be served by a webserver on the media URL DJANGO_MEDIA_VOL=/path/to/media/root +# folder for DB +PGDATA_VOL=/path/to/pgdata + # Port to serve the App PORT=8000 diff --git a/compose.yaml b/compose.yaml index b9c9bb4..8182ea6 100644 --- a/compose.yaml +++ b/compose.yaml @@ -35,7 +35,7 @@ services: POSTGRES_PASSWORD: "${DJANGO_POSTGRESQL_PW:-p4ssw0rd}" POSTGRES_DB: "shimatta_kenkyusho" volumes: - - "${PGDATA:-./run/pgdata}:/var/lib/postgresql/data" + - "${PGDATA_VOL:-./run/pgdata}:/var/lib/postgresql/data" networks: - backendnet healthcheck: From 8a8f2cdea4872075954521d59e54b8f6d42860ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 17 Nov 2024 20:08:53 +0100 Subject: [PATCH 9/9] Fix typo in comment --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index ab72682..d92e9d3 100644 --- a/.env.example +++ b/.env.example @@ -18,7 +18,7 @@ PORT=8000 # Secret Key. Must be edited before deployment DJANGO_SECRET_KEY=534hj5jgh4365ghj35jgh245jgh24 -# Allowed host be be accessed. Currently it is only possible to specify a single URL +# Allowed host to be accessed. Currently it is only possible to specify a single URL DJANGO_ALLOWED_HOST=lab.example.com # Media URL for images and other content