Добавил разделение баз данных. Ну и первая попытка настроить деплой
Some checks failed
Auto-Deploy-prodman / deploy (push) Failing after 1s

This commit is contained in:
2026-02-14 23:20:44 +03:00
parent e77237ca5e
commit 97c187ac97
9 changed files with 172 additions and 13 deletions

10
.env Normal file
View File

@@ -0,0 +1,10 @@
# Настройки базы данных
DB_NAME=prodman_db
DB_USER=prodman_user
DB_PASS=prodman_password_zwE45t!
# Настройки Django
ENV_TYPE=server
DB_HOST=db
# todo потом установить домен для продакшена
ALLOWED_HOSTS=yourdomain.com,123.123.123.123,web

View File

@@ -0,0 +1,15 @@
name: Auto-Deploy-prodman
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
deploy:
runs-on: host-shell # Твоя новая метка!
steps:
- name: Shell Deploy
run: |
cd /home/ack/projects/prodman
git pull origin main
docker compose up -d --build

2
.gitignore vendored
View File

@@ -30,7 +30,7 @@ staticfiles/ # Собранные статические файлы (collects
*.pot *.pot
# Environments # Environments
.env # .env
.venv .venv
env/ env/
venv/ venv/

23
Dockerfile Normal file
View File

@@ -0,0 +1,23 @@
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc libpq-dev && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Копируем скрипт входа
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
# Команда по умолчанию
CMD ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]

View File

@@ -13,8 +13,8 @@ class BaseOperation(PolymorphicModel):
class Meta: class Meta:
ordering = ['order'] ordering = ['order']
verbose_name = "Операция" verbose_name = "Технологическая операция"
verbose_name_plural = "Операции" verbose_name_plural = "Технологический маршрут"
def __str__(self): def __str__(self):
return f"{self.order}. {self._meta.verbose_name}" return f"{self.order}. {self._meta.verbose_name}"
@@ -35,6 +35,8 @@ class LaserCutSheet(BaseOperation):
pierces = models.IntegerField("Количество проколов", default=1) pierces = models.IntegerField("Количество проколов", default=1)
dxf_file = models.FileField("DXF файл", upload_to='dxf_files/%Y/%m', null=True, blank=True) dxf_file = models.FileField("DXF файл", upload_to='dxf_files/%Y/%m', null=True, blank=True)
#todo: добавить использование азота
def clean(self): def clean(self):
if self.cut_length < 1: if self.cut_length < 1:
raise ValidationError("Длина реза должна быть больше 0!") raise ValidationError("Длина реза должна быть больше 0!")

View File

@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/6.0/ref/settings/
""" """
from pathlib import Path from pathlib import Path
import os
# 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
@@ -22,10 +23,19 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-5(p6^by%ax10=(ev#ltdb8#f4@mq4&9gqnjvr9dboc=7t_&sbf' SECRET_KEY = 'django-insecure-5(p6^by%ax10=(ev#ltdb8#f4@mq4&9gqnjvr9dboc=7t_&sbf'
# SECURITY WARNING: don't run with debug turned on in production! # читаем переменную окружения
DEBUG = True ENV_TYPE = os.getenv('ENV_TYPE', 'local')
ALLOWED_HOSTS = [] # Настройки безопасности
# DEBUG будет True везде, кроме сервера
DEBUG = ENV_TYPE != 'server'
if not DEBUG:
# На сервере список хостов должен быть ограничен
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
else:
# Для разработки разрешаем всё
ALLOWED_HOSTS = ['*']
# Application definition # Application definition
@@ -57,7 +67,9 @@ ROOT_URLCONF = 'core.urls'
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], 'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@@ -71,10 +83,36 @@ TEMPLATES = [
WSGI_APPLICATION = 'core.wsgi.application' WSGI_APPLICATION = 'core.wsgi.application'
print(f"DEBUG: Current ENV_TYPE is {ENV_TYPE}")
# Database # Database
# https://docs.djangoproject.com/en/6.0/ref/settings/#databases # https://docs.djangoproject.com/en/6.0/ref/settings/#databases
if ENV_TYPE == 'server':
# Для Docker на удаленном сервере (максимальная защита через .env)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASS'),
'HOST': os.getenv('DB_HOST', 'db'),
'PORT': '5432',
}
}
elif ENV_TYPE == 'dev':
# Настройки для локальной разработки с внешней БД
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'prodman_dev_db',
'USER': 'dev_user',
'PASSWORD': 'dev_password',
'HOST': '192.168.1.90', # локальный сервер БД
'PORT': '5432',
}
}
else:
# Режим "на коленке"
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
@@ -117,4 +155,9 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/6.0/howto/static-files/ # https://docs.djangoproject.com/en/6.0/howto/static-files/
# --- Статика и Медиа ---
STATIC_URL = 'static/' STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'

53
docker-compose.yml Normal file
View File

@@ -0,0 +1,53 @@
name: prodman
services:
db:
image: postgres:15-alpine
restart: always
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
- postgres_data:/var/lib/postgresql/data
web:
build: .
# Загружаем переменные окружения в settings.py
env_file:
- .env
# Пока не убираем, вопрос возникает о дбхосте
# environment:
# - ENV_TYPE={ENV_TYPE}
# - DB_NAME={DB_NAME}
# - DB_USER={DB_USER}
# - DB_PASS={DB_PASS}
# - DB_HOST=db
volumes:
- staticfiles:/app/staticfiles # Сюда статику
- mediafiles:/app/media # Сюда медиа
# - .:/app
expose:
- "8000"
depends_on:
- db
nginx:
image: nginx:1.25-alpine
volumes:
# Подключаем конфиг и статику с медиа в режиме только для чтения (т.к. nginx смотрит в интернет и может быть подвергнута атаке)
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- staticfiles:/app/staticfiles:ro
- mediafiles:/app/media:ro
ports:
- "8081:80"
depends_on:
- web
volumes:
postgres_data:
staticfiles:
mediafiles:

13
entrypoint.sh Normal file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
# Собираем статику
echo "Collecting static files..."
python manage.py collectstatic --noinput
# Применяем миграции базы данных
echo "Applying database migrations..."
python manage.py migrate --noinput
# Запускаем основную команду (Gunicorn)
echo "Starting Gunicorn..."
exec "$@"

Binary file not shown.