diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..e62d6918 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.idea/ +.vscode/ +*.iml +.env +.DS_Store +venv/ +.pytest_cache/ +**__pycache__/ +**db.sqlite3 +media \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c45fa34c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.10-slim + +ENV PYTHONUNBUFFERED=1 +WORKDIR /app + +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt + +COPY . . +RUN mkdir -p /app/media +RUN adduser \ + --disabled-password \ + --no-create-home \ + my_user +RUN chown -R my_user /app/media +RUN chmod -R 755 /media + + +USER my_user diff --git a/cinema/management/__init__.py b/cinema/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cinema/management/commands/__init__.py b/cinema/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cinema/management/commands/wait_for_db.py b/cinema/management/commands/wait_for_db.py new file mode 100644 index 00000000..35d76340 --- /dev/null +++ b/cinema/management/commands/wait_for_db.py @@ -0,0 +1,29 @@ +import time +from django.core.management.base import BaseCommand +from django.db import connections +from django.db.utils import OperationalError + + +class Command(BaseCommand): + """Wait for db connection""" + + def handle(self, *args, **options): + self.stdout.write("Checking database connection...") + + db_conn = None + attempts = 0 + while not db_conn and attempts < 15: + try: + db_conn = connections["default"] + db_conn.cursor() + except OperationalError: + attempts += 1 + self.stdout.write( + f"DB is not ready(attempt {attempts}/15)... " + f"Wait for 2 seconds." + ) + time.sleep(2) + else: + self.stdout.write( + self.style.SUCCESS("DB is ready, continue...") + ) diff --git a/cinema/migrations/0002_alter_movie_actors_alter_movie_genres_and_more.py b/cinema/migrations/0002_alter_movie_actors_alter_movie_genres_and_more.py new file mode 100644 index 00000000..7232d854 --- /dev/null +++ b/cinema/migrations/0002_alter_movie_actors_alter_movie_genres_and_more.py @@ -0,0 +1,41 @@ +# Generated by Django 6.0.5 on 2026-05-24 18:40 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cinema', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterField( + model_name='movie', + name='actors', + field=models.ManyToManyField(blank=True, related_name='movies', to='cinema.actor'), + ), + migrations.AlterField( + model_name='movie', + name='genres', + field=models.ManyToManyField(blank=True, related_name='movies', to='cinema.genre'), + ), + migrations.AlterField( + model_name='moviesession', + name='cinema_hall', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='movie_sessions', to='cinema.cinemahall'), + ), + migrations.AlterField( + model_name='moviesession', + name='movie', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='movie_sessions', to='cinema.movie'), + ), + migrations.AlterField( + model_name='order', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 90dde772..62a253d2 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -9,6 +9,7 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.0/ref/settings/ """ +import os from datetime import timedelta from pathlib import Path @@ -27,8 +28,8 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] - +ALLOWED_HOSTS = ["127.0.0.1"] +STATIC_ROOT = BASE_DIR / "staticfiles" INTERNAL_IPS = [ "127.0.0.1", ] @@ -86,8 +87,12 @@ DATABASES = { "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", + "ENGINE": "django.db.backends.postgresql", + "NAME": os.environ["POSTGRES_DB"], + "USER": os.environ["POSTGRES_USER"], + "PASSWORD": os.environ["POSTGRES_PASSWORD"], + "HOST": os.environ["POSTGRES_HOST"], + "PORT": os.environ["POSTGRES_PORT"], } } diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..f6cdc41d --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,27 @@ +services: + app: + build: + context: . + env_file: + - .env + ports: + - "8000:8000" + volumes: + - my_media:/app/media + command: + sh -c "python manage.py wait_for_db && python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000" + depends_on: + - db + + db: + image: postgres:16.0-alpine3.17 + restart: always + env_file: + - .env + ports: + - "5432:5432" + volumes: + - my_db:$PGDATA +volumes: + my_db: + my_media: diff --git a/requirements.txt b/requirements.txt index 2dc12c67..79947234 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,28 @@ -django -flake8 -flake8-quotes -flake8-variables-names -pep8-naming -django-debug-toolbar -djangorestframework -djangorestframework-simplejwt -drf-spectacular -Pillow +asgiref==3.11.1 +attrs==26.1.0 +Django==4.2.15 +django-debug-toolbar==6.3.0 +djangorestframework==3.17.1 +djangorestframework_simplejwt==5.5.1 +drf-spectacular==0.29.0 +flake8==7.3.0 +flake8-quotes==3.4.0 +flake8-variables-names==0.0.6 +inflection==0.5.1 +jsonschema==4.26.0 +jsonschema-specifications==2025.9.1 +mccabe==0.7.0 +pep8-naming==0.15.1 +pillow==12.2.0 +psycopg==3.3.4 +psycopg-binary==3.3.4 +pycodestyle==2.14.0 +pyflakes==3.4.0 +PyJWT==2.13.0 +PyYAML==6.0.3 +referencing==0.37.0 +rpds-py==0.30.0 +setuptools==82.0.1 +sqlparse==0.5.5 +tzdata==2026.2 +uritemplate==4.2.0