Compare commits

...

11 Commits

Author SHA1 Message Date
390eaac396 Merge branch 'develop' into feature/csv-import 2024-11-17 21:44:53 +01:00
1c08f433d4 Merge pull request 'Implement #11 mhu/11-add-docker-compose-setup: Add compose setup' (#12) from mhu/11-add-docker-compose-setup into develop
Reviewed-on: #12
Reviewed-by: Stefan Strobel <stefan.strobel@shimatta.net>
2024-11-17 20:19:28 +01:00
8a8f2cdea4 Fix typo in comment 2024-11-17 20:08:53 +01:00
66f4eea77d Update env file example to contain Volume mount point for DB folder 2024-11-17 19:36:27 +01:00
561b2aed27 Add the /healthcheck path which returns an HTTP200 OK response for checking the helath of the container after startup 2024-11-17 19:10:28 +01:00
a59fad4866 Add self hosted entrypoint file for easier debugging which will use the integrated django server to serve all files 2024-11-17 17:33:45 +01:00
144a65ee05 Fix typo in eample env file 2024-11-17 16:52:18 +01:00
fc5fa9f740 Fix startup issue with postgres on first start. Implement health check of postgres and delay django container until it's healthy. 2024-11-17 16:50:10 +01:00
d2ce635f05 Add compose setup
* Use a dedicated postgresql container as database
* Controlled via .env file
* Ecample script for interactive container startup
2024-11-17 16:37:23 +01:00
64d0a1bfb3 Make gunicorn listen to all incoming IPs on Port 8000. This is necessary to use a spearate net with the postgres container. 2024-11-17 16:36:36 +01:00
b057fedb5f Add optional env variable DJANGO_FORCE_DEV_MODE to force production settings to dev mode for debugging 2024-11-17 16:34:58 +01:00
10 changed files with 119 additions and 5 deletions

32
.env.example Normal file
View File

@ -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

3
.gitignore vendored
View File

@ -125,3 +125,6 @@ dmypy.json
myenv/* myenv/*
run/*
.env

View File

@ -1,5 +1,5 @@
FROM alpine:latest 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 COPY . /home/shimatta/kenkyusho
WORKDIR /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 RUN python3 -m venv /home/shimatta/kenkyusho/.venv && . /home/shimatta/kenkyusho/.venv/bin/activate && pip install -r requirements.txt

48
compose.yaml Normal file
View File

@ -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:

View File

@ -3,4 +3,4 @@ source /home/shimatta/kenkyusho/.venv/bin/activate
cd /home/shimatta/kenkyusho/shimatta_kenkyusho cd /home/shimatta/kenkyusho/shimatta_kenkyusho
python manage.py migrate --settings shimatta_kenkyusho.settings_production python manage.py migrate --settings shimatta_kenkyusho.settings_production
python manage.py collectstatic --settings shimatta_kenkyusho.settings_production --noinput 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

6
entrypoint_self_hosted.sh Executable file
View File

@ -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

View File

@ -16,4 +16,5 @@ urlpatterns = [
path('distributors/<slug:uuid>/', parts_views.DistributorDetailView.as_view(), name='parts-distributors-detail'), path('distributors/<slug:uuid>/', parts_views.DistributorDetailView.as_view(), name='parts-distributors-detail'),
path('manufacturers/', parts_views.ManufacturersViewSet.as_view(), name='parts-manufacturers'), path('manufacturers/', parts_views.ManufacturersViewSet.as_view(), name='parts-manufacturers'),
path("manufacturers/<slug:uuid>/", parts_views.ManufacturerDetailViewSet.as_view(), name='parts-manufacturers-detail'), path("manufacturers/<slug:uuid>/", parts_views.ManufacturerDetailViewSet.as_view(), name='parts-manufacturers-detail'),
path("healthcheck/", parts_views.health_check_view, name='parts-health-check'),
] ]

View File

@ -19,8 +19,10 @@ from .component_import import import_components_from_csv
from django.db.models import Q from django.db.models import Q
from django.db.models.functions import Lower from django.db.models.functions import Lower
from django.forms import formset_factory from django.forms import formset_factory
from django.http import HttpResponse
import uuid import uuid
ParameterSearchFormSet = formset_factory(ComponentParameterSearchForm, extra=1) ParameterSearchFormSet = formset_factory(ComponentParameterSearchForm, extra=1)
class QrSearchForm(forms.Form): class QrSearchForm(forms.Form):
@ -970,4 +972,12 @@ class ManufacturerDetailViewSet(LoginRequiredMixin, BaseTemplateMixin, DetailVie
elif 'submit-manufacturer-edit' in request.POST: elif 'submit-manufacturer-edit' in request.POST:
return self.edit_manufacturer(request) return self.edit_manufacturer(request)
return super().post(request, *args, **kwargs) 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)

View File

@ -16,9 +16,13 @@ The following environment variables have to be set:
- DJANGO_MEDIA_URL - DJANGO_MEDIA_URL
- DJANGO_MEDIA_ROOT - DJANGO_MEDIA_ROOT
- DJANGO_POSTGRESQL_SOCKET - DJANGO_POSTGRESQL_SOCKET
- DJANGO_POSTGRESQL_PORT
The following can be set 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_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! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False 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 # Application definition
@ -232,4 +239,4 @@ CSRF_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = False SECURE_SSL_REDIRECT = False
SECURE_HSTS_SECONDS = get_env_value('DJANGO_SECURE_HSTS_SECONDS', default=120) SECURE_HSTS_SECONDS = get_env_value('DJANGO_SECURE_HSTS_SECONDS', default=120)

View File

@ -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