From 0610053a3ea4e20972d570ca9761430ffbd73f0f Mon Sep 17 00:00:00 2001 From: WGAVermeer <90707235+WGAVermeer@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:44:17 +0100 Subject: [PATCH] added nginx as a proxy. Still need to enable ssl. --- .docker-compose-files/compose.check.yaml | 14 ++++++ .../compose.dev.yaml | 0 .../compose.prod.yaml | 0 .../compose.test.yaml | 1 + .nginx/.conf | 3 ++ .nginx/.templates/nginx.conf.template | 49 +++++++++++++++++++ Makefile | 11 +++-- compose.yaml | 30 ++++++++++-- src/polls/admin.py | 4 ++ src/polls/migrations/0001_initial.py | 32 ++++++++++++ src/polls/models.py | 17 +++++++ src/website/settings.py | 6 ++- 12 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 .docker-compose-files/compose.check.yaml rename compose.dev.yaml => .docker-compose-files/compose.dev.yaml (100%) rename compose.prod.yaml => .docker-compose-files/compose.prod.yaml (100%) rename compose.test.yaml => .docker-compose-files/compose.test.yaml (99%) create mode 100644 .nginx/.conf create mode 100644 .nginx/.templates/nginx.conf.template create mode 100644 src/polls/migrations/0001_initial.py diff --git a/.docker-compose-files/compose.check.yaml b/.docker-compose-files/compose.check.yaml new file mode 100644 index 0000000..99a70d9 --- /dev/null +++ b/.docker-compose-files/compose.check.yaml @@ -0,0 +1,14 @@ +services: + web: + command: python manage.py check --deploy + restart: "no" + env_file: + - path: .env.template + required: true + + + db: + env_file: + - path: .env.template + required: true + diff --git a/compose.dev.yaml b/.docker-compose-files/compose.dev.yaml similarity index 100% rename from compose.dev.yaml rename to .docker-compose-files/compose.dev.yaml diff --git a/compose.prod.yaml b/.docker-compose-files/compose.prod.yaml similarity index 100% rename from compose.prod.yaml rename to .docker-compose-files/compose.prod.yaml diff --git a/compose.test.yaml b/.docker-compose-files/compose.test.yaml similarity index 99% rename from compose.test.yaml rename to .docker-compose-files/compose.test.yaml index e98c2c6..6609ef5 100644 --- a/compose.test.yaml +++ b/.docker-compose-files/compose.test.yaml @@ -6,6 +6,7 @@ services: - path: .env.template required: true + db: env_file: - path: .env.template diff --git a/.nginx/.conf b/.nginx/.conf new file mode 100644 index 0000000..d3c3d9d --- /dev/null +++ b/.nginx/.conf @@ -0,0 +1,3 @@ +events {} + +http {} diff --git a/.nginx/.templates/nginx.conf.template b/.nginx/.templates/nginx.conf.template new file mode 100644 index 0000000..a67310b --- /dev/null +++ b/.nginx/.templates/nginx.conf.template @@ -0,0 +1,49 @@ +server { + listen ${NGINX_PORT}; + server_name ${NGINX_HOSTNAME}; + + location /static/ { + alias /app/static/; + expires 30d; + add_header Cache-Control "public"; + } + + location /media/ { + alias /app/media; + expires 30d; + add_header Cache-Control "public"; + } + + location / { + proxy_pass http://web:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + +server { + listen ${NGINX_SSL_PORT}; + server_name ${NGINX_HOSTNAME}; + + location /static/ { + alias /app/static/; + expires 30d; + add_header Cache-Control "public"; + } + + location /media/ { + alias /app/media; + expires 30d; + add_header Cache-Control "public"; + } + + location / { + proxy_pass http://web:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/Makefile b/Makefile index c61f5ba..ea16be1 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,16 @@ prod: docker compose down - docker compose -f ./compose.yaml -f ./compose.prod.yaml up -d --build + docker compose -f ./compose.yaml -f ./.docker-compose-files/compose.prod.yaml up -d --build + docker exec quatsh-website-web-1 python manage.py collectstatic --noinput + docker exec quatsh-website-web-1 python manage.py check --deploy + docker exec quatsh-website-web-1 python manage.py migrate dev: docker compose down - docker compose -f ./compose.yaml -f ./compose.dev.yaml up --build -d + docker compose -f ./compose.yaml -f ./.docker-compose-files/compose.dev.yaml up --build -d + docker exec quatsh-website-web-1 python manage.py collectstatic --noinput docker exec -it quatsh-website-web-1 sh test: - docker compose --env-file .env.template -f ./compose.yaml -f ./compose.test.yaml up --build --abort-on-container-exit --exit-code-from web + docker compose --env-file .env.template -f ./compose.yaml -f ./.docker-compose_files up --build --abort-on-container-exit --exit-code-from web + diff --git a/compose.yaml b/compose.yaml index 4c14151..eda301a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,16 +1,21 @@ services: web: build: . - command: gunicorn --proxy-protocol auto --proxy-allow-from 10.10.50.11 website.wsgi:application + command: gunicorn website.wsgi:application depends_on: - db - ports: - - 8000:8000 environment: + ALLOWED_HOSTS: ${NGINX_HOSTNAME} PYTHONDONTWRITEBYTECODE: 1 PYTHONUNBUFFERED: 1 DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE} + VIRTUAL_HOST: localhost + #VIRTUAL_PORT: 8000 restart: unless-stopped + volumes: + - static_volume:/app/static + - media_volume:/app/media + db: image: postgres:18 @@ -30,6 +35,23 @@ services: ports: - 8080:8080 + proxy: + image: nginx:stable + volumes: + - ./.nginx/.templates:/etc/nginx/templates + - static_volume:/app/static:ro + - media_volume:/app/media:ro + restart: unless-stopped + ports: + - 80:80 + - 443:443 + environment: + - NGINX_HOSTNAME=${NGINX_HOSTNAME} + - NGINX_PORT=80 + - NGINX_SSL_PORT=443 + depends_on: + - web + test: build: . command: python manage.py test @@ -41,3 +63,5 @@ services: volumes: postgres_data: + static_volume: + media_volume: diff --git a/src/polls/admin.py b/src/polls/admin.py index 8c38f3f..d0e6a57 100644 --- a/src/polls/admin.py +++ b/src/polls/admin.py @@ -1,3 +1,7 @@ from django.contrib import admin # Register your models here. + +from .models import Question + +admin.site.register(Question) diff --git a/src/polls/migrations/0001_initial.py b/src/polls/migrations/0001_initial.py new file mode 100644 index 0000000..65683f4 --- /dev/null +++ b/src/polls/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# Generated by Django 6.0.3 on 2026-03-25 14:26 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Question', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('question_text', models.CharField(max_length=200)), + ('pub_date', models.DateTimeField(verbose_name='date published')), + ], + ), + migrations.CreateModel( + name='Choice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('choice_text', models.CharField(max_length=200)), + ('votes', models.IntegerField(default=0)), + ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.question')), + ], + ), + ] diff --git a/src/polls/models.py b/src/polls/models.py index 71a8362..76e8101 100644 --- a/src/polls/models.py +++ b/src/polls/models.py @@ -1,3 +1,20 @@ from django.db import models # Create your models here. + + +class Question(models.Model): + question_text = models.CharField(max_length=200) + pub_date = models.DateTimeField("date published") + + def __str__(self): + return self.question_text + + +class Choice(models.Model): + question = models.ForeignKey(Question, on_delete=models.CASCADE) + choice_text = models.CharField(max_length=200) + votes = models.IntegerField(default=0) + + def __str__(self): + return self.choice_text diff --git a/src/website/settings.py b/src/website/settings.py index 0264fb5..2ee0b3b 100644 --- a/src/website/settings.py +++ b/src/website/settings.py @@ -24,15 +24,16 @@ BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = bool(os.getenv("DEBUG", False)) +DEBUG = os.getenv("DEBUG") == "TRUE" -ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS").split(",") +ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "127.0.0.1").split(",") SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") # Application definition INSTALLED_APPS = [ + "polls.apps.PollsConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -120,4 +121,5 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/6.0/howto/static-files/ +STATIC_ROOT = "/app/static/" STATIC_URL = "static/"