diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d92e9d3 --- /dev/null +++ b/.env.example @@ -0,0 +1,32 @@ +#################################################################################################### +# 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 + +# folder for DB +PGDATA_VOL=/path/to/pgdata + +# Port to serve the App +PORT=8000 + +# Secret Key. Must be edited before deployment +DJANGO_SECRET_KEY=534hj5jgh4365ghj35jgh245jgh24 + +# 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 +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 confined 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/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 new file mode 100644 index 0000000..8182ea6 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,48 @@ +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: + 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 + environment: + POSTGRES_PASSWORD: "${DJANGO_POSTGRESQL_PW:-p4ssw0rd}" + POSTGRES_DB: "shimatta_kenkyusho" + volumes: + - "${PGDATA_VOL:-./run/pgdata}:/var/lib/postgresql/data" + networks: + - backendnet + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + +networks: + backendnet: 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 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 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 7cf3562..631ee7d 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -19,8 +19,10 @@ from .component_import import import_components_from_csv 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): @@ -970,4 +972,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 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) 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