Merge branch 'main' of https://git.intra.yksa.space/afanasyev.aa/api-drf-1
This commit is contained in:
commit
433dcef8d4
8 changed files with 206 additions and 40 deletions
36
.dockerignore
Normal file
36
.dockerignore
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
__pycache__
|
||||||
|
**/__pycache__
|
||||||
|
**/__pycache__/*
|
||||||
|
venv
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.sqlite3
|
||||||
|
.Python
|
||||||
|
env
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
.tox
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.log
|
||||||
|
.git
|
||||||
|
.vscode
|
||||||
|
.prettierrc
|
||||||
|
.mypy_cache
|
||||||
|
.pytest_cache
|
||||||
|
.hypothesis
|
||||||
|
Dockerfile
|
||||||
|
.env
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.override.yml
|
||||||
|
docker-compose.override
|
||||||
|
docker-compose.yml
|
||||||
|
nginx
|
||||||
|
media
|
||||||
|
static
|
||||||
|
postgres
|
||||||
80
Dockerfile
80
Dockerfile
|
|
@ -1,20 +1,76 @@
|
||||||
# Базовый образ
|
FROM python:3.13-slim AS builder
|
||||||
FROM python:3.11
|
|
||||||
|
|
||||||
# Устанавливаем рабочую директорию внутри контейнера
|
RUN mkdir /www
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Копируем зависимости
|
WORKDIR /www
|
||||||
COPY requirements.txt .
|
|
||||||
|
|
||||||
# Устанавливаем зависимости
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
# libpq-dev \
|
||||||
|
# gcc \
|
||||||
|
# g++ \
|
||||||
|
# libffi-dev \
|
||||||
|
# libssl-dev \
|
||||||
|
# libxml2-dev \
|
||||||
|
# libxslt1-dev \
|
||||||
|
# zlib1g-dev \
|
||||||
|
# libjpeg-dev \
|
||||||
|
# libfreetype6-dev && \
|
||||||
|
# rm -rf /var/lib/apt/lists/* && \
|
||||||
|
# apt-get clean && \
|
||||||
|
# apt-get autoclean
|
||||||
|
|
||||||
|
RUN pip install --upgrade pip
|
||||||
|
|
||||||
|
COPY requirements.txt /www/
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Копируем все файлы проекта
|
COPY requirements-prod.txt /www/
|
||||||
COPY . .
|
RUN pip install --no-cache-dir -r requirements-prod.txt
|
||||||
|
|
||||||
# Открываем порт (опционально, если хочешь)
|
# Stage 2: Production stage
|
||||||
|
FROM python:3.13-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libpq-dev \
|
||||||
|
libssl-dev \
|
||||||
|
gettext && \
|
||||||
|
apt-get clean && \
|
||||||
|
apt-get autoclean
|
||||||
|
|
||||||
|
RUN useradd -m -r wwwuser && \
|
||||||
|
mkdir /www && \
|
||||||
|
chown -R wwwuser /www
|
||||||
|
|
||||||
|
# Copy the Python dependencies from the builder stage
|
||||||
|
COPY --from=builder /usr/local/lib/python3.13/site-packages/ /usr/local/lib/python3.13/site-packages/
|
||||||
|
COPY --from=builder /usr/local/bin/ /usr/local/bin/
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /www
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
COPY --chown=wwwuser:wwwuser . .
|
||||||
|
|
||||||
|
RUN chmod +x /www/entrypoint.sh && \
|
||||||
|
chmod +x /www/manage.py
|
||||||
|
|
||||||
|
RUN mkdir -p /static && \
|
||||||
|
mkdir -p /media && \
|
||||||
|
chown -R wwwuser:wwwuser /static && \
|
||||||
|
chown -R wwwuser:wwwuser /media
|
||||||
|
|
||||||
|
# Set environment variables to optimize Python
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER wwwuser
|
||||||
|
|
||||||
|
# Expose the application port
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# Запускаем сервер
|
# Run Django’s development server
|
||||||
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
CMD ["/www/entrypoint.sh"]
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
|
|
@ -7,24 +9,40 @@ services:
|
||||||
POSTGRES_PASSWORD: mypass
|
POSTGRES_PASSWORD: mypass
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
ports:
|
networks:
|
||||||
- "5432:5432"
|
- app_network
|
||||||
|
|
||||||
web:
|
web:
|
||||||
build: .
|
build: .
|
||||||
command: python manage.py runserver 0.0.0.0:8000
|
|
||||||
volumes:
|
|
||||||
- .:/app
|
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- ./static:/static:rw
|
||||||
|
- ./media:/media:rw
|
||||||
|
env_file: .env
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
environment:
|
networks:
|
||||||
- DB_NAME=mydb
|
- app_network
|
||||||
- DB_USER=myuser
|
|
||||||
- DB_PASSWORD=mypass
|
nginx:
|
||||||
- DB_HOST=db
|
image: nginx:latest
|
||||||
- DB_PORT=5432
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
- ./static:/var/www/static
|
||||||
|
- ./media:/var/www/media
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
networks:
|
||||||
|
- app_network
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
static_volume:
|
||||||
|
media_volume:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app_network:
|
||||||
|
driver: bridge
|
||||||
4
entrypoint.sh
Normal file
4
entrypoint.sh
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
python manage.py collectstatic --noinput
|
||||||
|
python manage.py migrate --noinput
|
||||||
|
python -m daphne testapi.asgi:application -b 0.0.0.0 -p 8000
|
||||||
34
nginx/nginx.conf
Normal file
34
nginx/nginx.conf
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
upstream django {
|
||||||
|
server web:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# Static files
|
||||||
|
location /static/ {
|
||||||
|
alias /app/static/;
|
||||||
|
expires 1y;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
gzip_static on;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Media files
|
||||||
|
location /media/ {
|
||||||
|
alias /app/media/;
|
||||||
|
expires 7d;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Django app
|
||||||
|
location / {
|
||||||
|
proxy_pass http://django;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
requirements-prod.txt
Normal file
1
requirements-prod.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
daphne
|
||||||
|
|
@ -6,4 +6,4 @@ drf-spectacular
|
||||||
requests
|
requests
|
||||||
django-cors-headers
|
django-cors-headers
|
||||||
Pillow
|
Pillow
|
||||||
|
python-dotenv
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
@ -19,16 +22,28 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# Environment flag
|
||||||
|
PRODUCTION = os.getenv('DJANGO_ENV') == 'production'
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'django-insecure-np(nxnh6mw)v4pa2n2z3pl_5&!2z$jshhak9r3v=y1u9rd*sl!'
|
SECRET_KEY = os.getenv(
|
||||||
|
'SECRET_KEY', 'django-insecure-np(nxnh6mw)v4pa2n2z3pl_5&!2z$jshhak9r3v=y1u9rd*sl!')
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = os.getenv('DEBUG', 'False') == 'True'
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split(',')
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
STATIC_URL = os.getenv('STATIC_URL', '/static/')
|
||||||
|
STATIC_ROOT = os.getenv('STATIC_ROOT', os.path.join(BASE_DIR, 'static'))
|
||||||
|
|
||||||
|
# Media files (user uploaded)
|
||||||
|
MEDIA_URL = os.getenv('MEDIA_URL', '/media/')
|
||||||
|
MEDIA_ROOT = os.getenv('MEDIA_ROOT', os.path.join(BASE_DIR, 'media')) # Куда сохранять загруженные файлы
|
||||||
|
|
||||||
|
|
||||||
# Application definitionЫ
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
|
|
@ -89,22 +104,22 @@ WSGI_APPLICATION = 'testapi.wsgi.application'
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||||
|
|
||||||
if DEBUG:
|
if PRODUCTION:
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'NAME': os.getenv('DB_NAME'),
|
||||||
|
'USER': os.getenv('DB_USER'),
|
||||||
|
'PASSWORD': os.getenv('DB_PASSWORD'),
|
||||||
|
'HOST': os.getenv('DB_HOST'),
|
||||||
|
'PORT': os.getenv('DB_PORT'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.postgresql',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': 'drfapi', # Your database name
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
'USER': 'postgres', # Your PostgreSQL username
|
|
||||||
'PASSWORD': '1235', # Your PostgreSQL password
|
|
||||||
'HOST': 'localhost', # Or your DB server's IP
|
|
||||||
'PORT': '5432', # Default PostgreSQL port
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,4 +191,6 @@ CSRF_COOKIE_SAMESITE = 'None' # temp
|
||||||
CSRF_COOKIE_SECURE = False
|
CSRF_COOKIE_SECURE = False
|
||||||
SESSION_COOKIE_SAMESITE = 'None' # temp
|
SESSION_COOKIE_SAMESITE = 'None' # temp
|
||||||
SESSION_COOKIE_SECURE = False
|
SESSION_COOKIE_SECURE = False
|
||||||
CSRF_TRUSTED_ORIGINS = ['http://localhost:5173', 'http://127.0.0.1:5173']
|
CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', '').split(',')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue