From 8a6d1b43f50910372bf03a9f0c123d8f2aa70f88 Mon Sep 17 00:00:00 2001 From: Eduard Tatarnikov <108517865+Edmaroff@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:55:52 +0800 Subject: [PATCH] add Docker --- .gitignore | 1 + docker-compose.yml | 61 ++++++++++++++++++ nginx/Dockerfile | 3 + nginx/nginx.conf | 30 +++++++++ retail_order_api/.dockerignore | 27 ++++++++ retail_order_api/.env.template | 12 ++-- retail_order_api/Dockerfile | 13 ++++ retail_order_api/backend/admin.py | 2 +- .../backend/migrations/0001_initial.py | 2 +- retail_order_api/backend/models.py | 3 + retail_order_api/entrypoint.sh | 10 +++ retail_order_api/requirements.txt | Bin 3530 -> 3614 bytes retail_order_api/retail_order_api/settings.py | 14 ++-- retail_order_api/tests/backend/test_api.py | 2 +- 14 files changed, 163 insertions(+), 17 deletions(-) create mode 100644 docker-compose.yml create mode 100644 nginx/Dockerfile create mode 100644 nginx/nginx.conf create mode 100644 retail_order_api/.dockerignore create mode 100644 retail_order_api/Dockerfile create mode 100644 retail_order_api/entrypoint.sh diff --git a/.gitignore b/.gitignore index 62e053a..a22c003 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ instance/ local_settings.py db.sqlite3 db.sqlite3-journal +static/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..af6015a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,61 @@ +version: '3.9' + +volumes: + postgres_volume: + static_volume: + media_volume: + +services: + # Database Postgres + db: + image: postgres:latest + container_name: postgres + env_file: + - ./retail_order_api/.env + volumes: + - postgres_volume:/var/lib/postgresql/data/ + ports: + - "5432:5432" + + # Django App + web: + build: ./retail_order_api + container_name: retail_order_api + ports: + - "8000:8000" + env_file: + - ./retail_order_api/.env + volumes: + - static_volume:/usr/src/app/static + - media_volume:/usr/src/app/media + depends_on: + - db + command: sh /usr/src/app/entrypoint.sh + + # web-server + nginx: + build: ./nginx + container_name: nginx + restart: on-failure + ports: + - '1337:80' + volumes: + - static_volume:/static + - media_volume:/media + depends_on: + - web + + # Redis + redis: + image: redis:latest + container_name: redis + ports: + - "6300:6379" + + # Celery + celery: + build: ./retail_order_api + command: celery -A retail_order_api worker -l info + depends_on: + - redis + - db \ No newline at end of file diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..212645d --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:1.24-alpine +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..71d04d3 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,30 @@ +upstream retail-order { + server retail_order_api:8000; +} + +server { + + listen 80; + server_name localhost; + + client_max_body_size 100M; + proxy_force_ranges on; + add_header Accept-Ranges bytes; + + location / { + proxy_ignore_client_abort on; + proxy_pass http://retail-order; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_redirect off; + } + + + location /static/ { + alias /static/; + } + + location /media/ { + alias /media/; + } +} \ No newline at end of file diff --git a/retail_order_api/.dockerignore b/retail_order_api/.dockerignore new file mode 100644 index 0000000..16d4c73 --- /dev/null +++ b/retail_order_api/.dockerignore @@ -0,0 +1,27 @@ +### main_dockerignore template +# Personal +manual.md +initial_task.md +README.md +static/ + +# Git +.gitignore +.git + +# Environments +venv_wsl +#.env +.venv +env/ +venv/ +venv_wsl/ +ENV/ +env.bak/ +venv.bak/ + +# PyCharm +.idea/ + +# Byte-compiled / optimized / DLL files +__pycache__/ \ No newline at end of file diff --git a/retail_order_api/.env.template b/retail_order_api/.env.template index 4715066..2b8e1d6 100644 --- a/retail_order_api/.env.template +++ b/retail_order_api/.env.template @@ -1,15 +1,15 @@ # Django SECRET_KEY=your_secret_key -DEBUG=True +DEBUG=True#Для Docker =True +ALLOWED_HOSTS=localhost,127.0.0.1 # PostgreSQL -ALLOWED_HOSTS=localhost,127.0.0.1 DB_ENGINE=django.db.backends.postgresql DB_NAME=your_db_name DB_USER=your_db_user DB_PASSWORD=your_db_password -DB_HOST=your_db_host -DB_PORT=your_db_port +DB_HOST=your_db_host#Для Docker =db +DB_PORT=your_db_port#Для Docker =5432 # SMTP EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend @@ -28,5 +28,5 @@ SOCIAL_AUTH_GITHUB_KEY=your_github_key SOCIAL_AUTH_GITHUB_SECRET=your_github_secret # Celery -CELERY_BROKER_URL=your_celery_broker_url -CELERY_RESULT_BACKEND=your_celery_result_backend +CELERY_BROKER_URL=your_celery_broker_url#Для Docker =redis://redis:6379 +CELERY_RESULT_BACKEND=your_celery_result_backend#Для Docker =redis://redis:6379 diff --git a/retail_order_api/Dockerfile b/retail_order_api/Dockerfile new file mode 100644 index 0000000..f7e781b --- /dev/null +++ b/retail_order_api/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.12-alpine + +WORKDIR /usr/src/app + +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERD 1 + +COPY requirements.txt /usr/src/app/requirements.txt + +RUN python3 -m pip install --upgrade pip +RUN pip3 install -r requirements.txt + +COPY . /usr/src/app diff --git a/retail_order_api/backend/admin.py b/retail_order_api/backend/admin.py index 13a8ab2..7f9c231 100644 --- a/retail_order_api/backend/admin.py +++ b/retail_order_api/backend/admin.py @@ -52,7 +52,7 @@ class CustomUserAdmin(UserAdmin): ), ( _("Permissions"), - {"fields": ("is_superuser", "groups", "user_permissions")}, + {"fields": ("is_active", "is_superuser", "groups", "user_permissions")}, ), (_("Important dates"), {"fields": ("last_login", "date_joined")}), ] diff --git a/retail_order_api/backend/migrations/0001_initial.py b/retail_order_api/backend/migrations/0001_initial.py index 486ab24..2e76619 100644 --- a/retail_order_api/backend/migrations/0001_initial.py +++ b/retail_order_api/backend/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.3 on 2024-03-22 04:40 +# Generated by Django 5.0.3 on 2024-03-28 09:41 import django.contrib.auth.validators import django.core.validators diff --git a/retail_order_api/backend/models.py b/retail_order_api/backend/models.py index f04215c..41ae8ad 100644 --- a/retail_order_api/backend/models.py +++ b/retail_order_api/backend/models.py @@ -39,9 +39,12 @@ def create_user(self, email, password=None, **extra_fields): def create_superuser(self, email, password, **extra_fields): extra_fields.setdefault("is_superuser", True) + extra_fields.setdefault("is_staff", True) if extra_fields.get("is_superuser") is not True: raise ValueError("Суперпользователь должен иметь is_superuser=True.") + if extra_fields.get("is_staff") is not True: + raise ValueError("Суперпользователь должен иметь is_staff=True.") return self._create_user(email, password, **extra_fields) diff --git a/retail_order_api/entrypoint.sh b/retail_order_api/entrypoint.sh new file mode 100644 index 0000000..d5f08cd --- /dev/null +++ b/retail_order_api/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +python manage.py makemigrations --noinput +python manage.py migrate --noinput +echo "Apply database migrations" +python manage.py shell -c "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.filter(username='root').exists() or User.objects.create_superuser('root@example.com', 'root')" +echo "Create SUPERUSER" +python manage.py collectstatic --no-input +echo "Starting server" +gunicorn retail_order_api.wsgi:application --bind 0.0.0.0:8000 diff --git a/retail_order_api/requirements.txt b/retail_order_api/requirements.txt index da4cd7e106559d9027e8162e4a01c9fad8de1f7f..3e173e10d136312eb50d4f66d63539e64c9426d9 100644 GIT binary patch delta 91 zcmX>lJx^xC5?1+ihEj$+hD?TJhJ1!1Aj=jAjTj6W^nj!ugTdzctjf%q#SE2T1qBT0 eKw({mB%p>ohD4x-N~i`s21}rF%gwtv_*ns!QW84= delta 17 ZcmbOyb4q%{64uQpSml^Ei*a(W0suXa1$h7f diff --git a/retail_order_api/retail_order_api/settings.py b/retail_order_api/retail_order_api/settings.py index 69253ce..9ac485c 100644 --- a/retail_order_api/retail_order_api/settings.py +++ b/retail_order_api/retail_order_api/settings.py @@ -64,15 +64,14 @@ WSGI_APPLICATION = "retail_order_api.wsgi.application" ROOT_URLCONF = "retail_order_api.urls" - DATABASES = { "default": { - "ENGINE": env.str("DB_ENGINE", "django.db.backends.sqlite3"), - "NAME": env.str("DB_NAME", os.path.join(BASE_DIR, "db.sqlite3")), - "USER": env.str("DB_USER", "user"), - "PASSWORD": env.str("DB_PASSWORD", "password"), - "HOST": env.str("DB_HOST", "localhost"), - "PORT": env.str("DB_PORT", "5432"), + "ENGINE": env.str("POSTGRES_ENGINE", "django.db.backends.sqlite3"), + "NAME": env.str("POSTGRES_DB", os.path.join(BASE_DIR, "db.sqlite3")), + "USER": env.str("POSTGRES_USER", "user"), + "PASSWORD": env.str("POSTGRES_PASSWORD", "password"), + "HOST": env.str("POSTGRES_HOST", "localhost"), + "PORT": env.str("POSTGRES_PORT", "5432"), } } @@ -210,7 +209,6 @@ CELERY_RESULT_BACKEND = env.str("CELERY_RESULT_BACKEND", "redis://localhost:6379") CELERY_BROKER_URL = env.str("CELERY_BROKER_URL", "redis://localhost:6379") - # django-baton BATON = { "SITE_HEADER": "retail-order-api", diff --git a/retail_order_api/tests/backend/test_api.py b/retail_order_api/tests/backend/test_api.py index df1c202..7d3abcf 100644 --- a/retail_order_api/tests/backend/test_api.py +++ b/retail_order_api/tests/backend/test_api.py @@ -284,7 +284,7 @@ def test_delete_shop(self, authenticated_client_shop, shop_factory): class TestProductDetailView: """Тесты для ProductDetailView.""" - url = reverse("backend:products_detail") + url = reverse("backend:products_in_shops") @staticmethod def assert_response(response, expected_ids):