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/.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 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 new file mode 100644 index 00000000..7ace31a5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +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 + + +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 90dde772..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", @@ -47,6 +48,7 @@ "debug_toolbar", "cinema", "user", + "core", ] MIDDLEWARE = [ @@ -85,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'), } } @@ -132,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/__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..0db61893 --- /dev/null +++ b/core/management/commands/wait_for_db.py @@ -0,0 +1,21 @@ +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: + 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!')) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..80d4277c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +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 + - static_data:/app/staticfiles + - media_data:/app/media + ports: + - "8000:8000" + environment: + - DB_HOST=db + - DB_NAME=cinema_db + - DB_USER=cinema_user + - DB_PASS=secretpassword + - ALLOWED_HOSTS=127.0.0.1,localhost + depends_on: + - db + +volumes: + postgres_data: + static_data: + media_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