From fe89c92f77577bc423562fabd21d172f6d555f47 Mon Sep 17 00:00:00 2001 From: Viktor Velychkocd Date: Sun, 19 Apr 2026 11:28:56 +0300 Subject: [PATCH 1/3] Solution --- .dockerignore | 8 +++++++ Dockerfile | 18 ++++++++++++++ cinema_service/settings.py | 1 + core/__init__.py | 0 core/management/__init__.py | 0 core/management/commands/__init__.py | 0 core/management/commands/wait_for_db.py | 19 +++++++++++++++ docker-compose.yml | 31 +++++++++++++++++++++++++ requirements.txt | 1 + 9 files changed, 78 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 core/__init__.py create mode 100644 core/management/__init__.py create mode 100644 core/management/commands/__init__.py create mode 100644 core/management/commands/wait_for_db.py create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..fbbf5933 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git +.venv +__pycache__ +*.pyc +db.sqlite3 +media/ +staticfiles/ +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..3126af82 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM python:3.11-slim + +ENV PYTHONUNBUFFERED=1 +WORKDIR /app + + +RUN apt-get update && apt-get install -y \ + gcc \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +RUN adduser --disabled-password --no-create-home django-user +USER django-user \ No newline at end of file diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 90dde772..75c703fc 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -47,6 +47,7 @@ "debug_toolbar", "cinema", "user", + "core", ] MIDDLEWARE = [ diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/management/__init__.py b/core/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/management/commands/__init__.py b/core/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/management/commands/wait_for_db.py b/core/management/commands/wait_for_db.py new file mode 100644 index 00000000..968ef319 --- /dev/null +++ b/core/management/commands/wait_for_db.py @@ -0,0 +1,19 @@ +import time +from django.core.management.base import BaseCommand +from django.db import connections +from django.db.utils import OperationalError + +class Command(BaseCommand): + """Django command to pause execution until database is available""" + + def handle(self, *args, **options): + self.stdout.write('Waiting for database...') + db_conn = None + while not db_conn: + try: + db_conn = connections['default'] + except OperationalError: + self.stdout.write('Database unavailable, waiting 1 second...') + time.sleep(1) + + self.stdout.write(self.style.SUCCESS('Database available!')) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..b6007bd8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +services: + db: + image: postgres:15-alpine + restart: always + environment: + POSTGRES_DB: cinema_db + POSTGRES_USER: cinema_user + POSTGRES_PASSWORD: secretpassword + volumes: + - postgres_data:/var/lib/postgresql/data + + app: + build: . + command: > + sh -c "python manage.py wait_for_db && + python manage.py migrate && + python manage.py runserver 0.0.0.0:8000" + volumes: + - .:/app + ports: + - "8000:8000" + environment: + - DB_HOST=db + - DB_NAME=cinema_db + - DB_USER=cinema_user + - DB_PASS=secretpassword + depends_on: + - db + +volumes: + postgres_data: \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2dc12c67..622155ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ djangorestframework djangorestframework-simplejwt drf-spectacular Pillow +psycopg2-binary From cd29f69f881c60a5cdc64c318c665b0a96d20d8d Mon Sep 17 00:00:00 2001 From: Viktor Velychkocd Date: Sun, 19 Apr 2026 11:41:01 +0300 Subject: [PATCH 2/3] Solution --- .github/workflows/test.yml | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c99a4a1a..a20161eb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,28 +1,11 @@ -name: Test +name: Docker Test -on: - pull_request: - branches: - - "master" +on: [push] jobs: - test: + build: runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout repo - uses: actions/checkout@v2 - - - name: Set Up Python 3.10 - uses: actions/setup-python@v2 - with: - python-version: "3.10" - - - name: Install requirements - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run flake8 - run: flake8 + - uses: actions/checkout@v3 + - name: Build and Run + run: docker compose build && docker compose up -d \ No newline at end of file From ac397454f0f226197afe2174e3bb927d707c0f3c Mon Sep 17 00:00:00 2001 From: Viktor Velychkocd Date: Sun, 19 Apr 2026 12:19:22 +0300 Subject: [PATCH 3/3] Solution --- .gitignore | 6 ++++++ Dockerfile | 7 +++++++ cinema_service/settings.py | 14 ++++++++++---- core/management/commands/wait_for_db.py | 6 ++++-- docker-compose.yml | 8 +++++++- 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 0b1609c6..617aa8a7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,9 @@ venv/ **__pycache__/ **db.sqlite3 media +.venv +.git +.gitignore +__pycache__ +*.pyc +db.sqlite3 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3126af82..7ace31a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,14 @@ RUN apt-get update && apt-get install -y \ COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt + COPY . . + RUN adduser --disabled-password --no-create-home django-user + + +RUN chown -R django-user:django-user /app + + USER django-user \ No newline at end of file diff --git a/cinema_service/settings.py b/cinema_service/settings.py index 75c703fc..a3ffef6f 100644 --- a/cinema_service/settings.py +++ b/cinema_service/settings.py @@ -11,6 +11,7 @@ """ from datetime import timedelta from pathlib import Path +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -27,7 +28,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "127.0.0.1,localhost").split(",") INTERNAL_IPS = [ "127.0.0.1", @@ -86,9 +87,13 @@ # https://docs.djangoproject.com/en/4.0/ref/settings/#databases DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ.get('DB_NAME', 'cinema_db'), + 'USER': os.environ.get('DB_USER', 'cinema_user'), + 'PASSWORD': os.environ.get('DB_PASS', 'secretpassword'), + 'HOST': os.environ.get('DB_HOST', 'db'), + 'PORT': os.environ.get('DB_PORT', '5432'), } } @@ -133,6 +138,7 @@ # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = "static/" +STATIC_ROOT = BASE_DIR / "staticfiles" MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" diff --git a/core/management/commands/wait_for_db.py b/core/management/commands/wait_for_db.py index 968ef319..0db61893 100644 --- a/core/management/commands/wait_for_db.py +++ b/core/management/commands/wait_for_db.py @@ -11,9 +11,11 @@ def handle(self, *args, **options): db_conn = None while not db_conn: try: - db_conn = connections['default'] + connection = connections['default'] + connection.cursor() + db_conn = True except OperationalError: self.stdout.write('Database unavailable, waiting 1 second...') time.sleep(1) - self.stdout.write(self.style.SUCCESS('Database available!')) \ No newline at end of file + self.stdout.write(self.style.SUCCESS('Database available!')) diff --git a/docker-compose.yml b/docker-compose.yml index b6007bd8..80d4277c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,12 +11,15 @@ services: app: build: . + # Команда, яка чекає базу, мігрує базу і запускає сервер command: > sh -c "python manage.py wait_for_db && python manage.py migrate && python manage.py runserver 0.0.0.0:8000" volumes: - .:/app + - static_data:/app/staticfiles + - media_data:/app/media ports: - "8000:8000" environment: @@ -24,8 +27,11 @@ services: - DB_NAME=cinema_db - DB_USER=cinema_user - DB_PASS=secretpassword + - ALLOWED_HOSTS=127.0.0.1,localhost depends_on: - db volumes: - postgres_data: \ No newline at end of file + postgres_data: + static_data: + media_data: \ No newline at end of file