Initial commit: setup deploy workflow
Some checks failed
Deploy timelaps / deploy (push) Failing after 1s
Some checks failed
Deploy timelaps / deploy (push) Failing after 1s
This commit is contained in:
25
.gitea/workflows/deploy.yaml
Normal file
25
.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Deploy timelaps
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: LabOnDeb
|
||||||
|
steps:
|
||||||
|
- name: Shell Deploy
|
||||||
|
run: |
|
||||||
|
# 1. Создаем папку, если её нет
|
||||||
|
mkdir -p /home/ack/projects/timelaps
|
||||||
|
cd /home/ack/projects/timelaps
|
||||||
|
|
||||||
|
# 2. Обновляем код напрямую через git (без checkout action)
|
||||||
|
if [ -d ".git" ]; then
|
||||||
|
git pull origin main
|
||||||
|
else
|
||||||
|
git clone https://gitea.tertelius.space/ack/timelaps.git .
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Запускаем сборку
|
||||||
|
docker compose up -d --build
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -174,3 +174,5 @@ cython_debug/
|
|||||||
# PyPI configuration file
|
# PyPI configuration file
|
||||||
.pypirc
|
.pypirc
|
||||||
|
|
||||||
|
#vscode files
|
||||||
|
.vscode/
|
||||||
41
Dockerfile
Normal file
41
Dockerfile
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Используем "легкую" версию Python на базе Debian Bookworm.
|
||||||
|
# slim — это баланс между размером образа и наличием нужных утилит.
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
# Указываем рабочую папку внутри контейнера. Все последующие команды будут выполняться в ней.
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Настройки окружения:
|
||||||
|
# 1. Запрещаем Python писать файлы .pyc (байткод) на диск, чтобы не мусорить.
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
# 2. Отключаем буферизацию логов. Так ты сразу увидишь ошибки в `docker logs`, а не будешь их ждать.
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# Ставим системные зависимости:
|
||||||
|
# apt-get update — обновляем списки пакетов.
|
||||||
|
# gcc и libpq-dev — необходимы для сборки библиотеки psycopg2 (драйвер для Postgres).
|
||||||
|
# rm -rf /var/lib/apt/lists/* — удаляем кэш установщика, чтобы уменьшить размер образа.
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ffmpeg \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Сначала копируем только список зависимостей.
|
||||||
|
# Это нужно для "кэширования слоев": если ты не менял библиотеки, Docker не будет переустанавливать их заново при сборке.
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Теперь копируем весь остальной код проекта в контейнер.
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Даем права на выполнение нашему скрипту запуска.
|
||||||
|
# Без этого контейнер может упасть с ошибкой "Permission denied".
|
||||||
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
|
# ENTRYPOINT — это команда, которая выполняется ВСЕГДА при старте.
|
||||||
|
# Наш скрипт подготовит базу (миграции) и соберет статику.
|
||||||
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
|
||||||
|
# CMD — это основная команда процесса.
|
||||||
|
# Запускаем Gunicorn, привязываем его к порту 8000 и ставим 3 рабочих процесса для скорости.
|
||||||
|
CMD ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3", "--timeout", "120"]
|
||||||
|
# Увеличиваем tineout до 120 секунд. Сборка видео может занять больше времени, чем 60 секунд.
|
||||||
62
docker-compose.yml
Normal file
62
docker-compose.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
name: prodman # Имя проекта, которое будет префиксом для всех контейнеров и сетей
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- БАЗА ДАННЫХ ---
|
||||||
|
# db:
|
||||||
|
# image: postgres:15-alpine # Легкий образ Postgres на базе Alpine Linux
|
||||||
|
# restart: unless-stopped # Перезапускать всегда, кроме случаев, когда ты сам его выключил
|
||||||
|
# environment:
|
||||||
|
# # Данные тянутся из твоего файла .env
|
||||||
|
# - POSTGRES_DB=${DB_NAME}
|
||||||
|
# - POSTGRES_USER=${DB_USER}
|
||||||
|
# - POSTGRES_PASSWORD=${DB_PASS}
|
||||||
|
# volumes:
|
||||||
|
# # Храним базу в именованном томе, чтобы данные не пропали при удалении контейнера
|
||||||
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
# --- ПРИЛОЖЕНИЕ (DJANGO) ---
|
||||||
|
web:
|
||||||
|
build: . # Собирает образ из Dockerfile в текущей папке
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- ENV_TYPE=server
|
||||||
|
env_file:
|
||||||
|
- .env # Прокидывает все секреты и настройки внутрь Python
|
||||||
|
volumes:
|
||||||
|
# Общие папки для статики и картинок. Сюда Django их складывает.
|
||||||
|
- staticfiles:/app/staticfiles
|
||||||
|
- mediafiles:/app/media
|
||||||
|
expose:
|
||||||
|
- "8000" # Открывает порт ТОЛЬКО внутри сети Docker для Nginx
|
||||||
|
|
||||||
|
# --- ВЕБ-СЕРВЕР (ФАСАД) ---
|
||||||
|
nginx:
|
||||||
|
image: nginx:1.25-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
# Основной конфиг маршрутизации
|
||||||
|
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
# Читаем статику и медиа, которые подготовил контейнер 'web'
|
||||||
|
# :ro (read-only) — защита: даже если Nginx взломают, файлы не удалят
|
||||||
|
- staticfiles:/app/staticfiles:ro
|
||||||
|
- mediafiles:/app/media:ro
|
||||||
|
ports:
|
||||||
|
- "80:80" # Единственная "дырка" в мир: порт 80 сервера -> порт 80 контейнера
|
||||||
|
depends_on:
|
||||||
|
- web # Nginx запустится только после Django
|
||||||
|
|
||||||
|
# Описание "жестких дисков" (Volumes), которые живут дольше контейнеров
|
||||||
|
volumes:
|
||||||
|
postgres_data: # Для данных БД
|
||||||
|
staticfiles: # Для CSS, JS и картинок интерфейса (collectstatic)
|
||||||
|
mediafiles: # Для загруженных тобой чертежей и фото
|
||||||
|
|
||||||
|
# Подключение NFS-шары напрямую в Docker
|
||||||
|
nfs_motioneye:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: nfs
|
||||||
|
# IP адрес твоего NAS или сервера, где лежит шара
|
||||||
|
o: addr=192.168.1.138,rw,nolock,soft
|
||||||
|
# Путь к папке на самом NFS сервере
|
||||||
|
device: ":/VideoStreaming"
|
||||||
15
entrypoint.sh
Normal file
15
entrypoint.sh
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Собираем статику в папку, которую увидит Nginx
|
||||||
|
echo "Collecting static files..."
|
||||||
|
python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
# Миграции
|
||||||
|
echo "Applying database migrations..."
|
||||||
|
python manage.py migrate --noinput
|
||||||
|
|
||||||
|
# Создаем админа (из переменных .env)
|
||||||
|
python manage.py createsuperuser --no-input || true
|
||||||
|
|
||||||
|
echo "Starting Gunicorn..."
|
||||||
|
exec "$@"
|
||||||
57
nginx/default.conf
Normal file
57
nginx/default.conf
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Описываем группу серверов, куда Nginx будет перекидывать запросы.
|
||||||
|
# 'web' — это имя сервиса из нашего docker-compose.yml.
|
||||||
|
upstream django_app {
|
||||||
|
server web:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
# Слушаем стандартный 80-й порт (HTTP).
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
# Список имен, на которые будет откликаться сервер.
|
||||||
|
# Если зайти по другому IP, Nginx может выдать ошибку.
|
||||||
|
server_name shiftflow.tertelius.space 192.168.1.108 localhost;
|
||||||
|
|
||||||
|
# Увеличиваем лимит загрузки (по умолчанию в Nginx всего 1МБ).
|
||||||
|
# 100М — чтобы ты мог спокойно грузить тяжелые чертежи или фото станков.
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Включаем Gzip-сжатие. Nginx будет сжимать текстовые файлы перед отправкой,
|
||||||
|
# что ускорит загрузку интерфейса, особенно на слабом интернете.
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml;
|
||||||
|
|
||||||
|
# Главный блок: всё, что не статика, летит в Django.
|
||||||
|
location / {
|
||||||
|
proxy_pass http://django_app;
|
||||||
|
|
||||||
|
# Передаем оригинальный домен/IP (нужно для ALLOWED_HOSTS в Django).
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
# Передаем реальный IP пользователя (чтобы в логах видеть, кто зашел).
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
|
# Передаем протокол (http или https).
|
||||||
|
# КРИТИЧНО для CSRF защиты, чтобы Django не ругался при входе в админку.
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Раздача статики (CSS, JS, картинки интерфейса).
|
||||||
|
# Nginx сам лезет в папку, не беспокоя Django — это очень быстро.
|
||||||
|
location /static/ {
|
||||||
|
# Путь ВНУТРИ контейнера Nginx (куда мы примонтировали волюм).
|
||||||
|
alias /app/staticfiles/;
|
||||||
|
# Заставляем браузер кэшировать стили на 30 дней, чтобы не качать их каждый раз.
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, no-transform";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Раздача медиа-файлов (чертежи, фото продукции).
|
||||||
|
location /media/ {
|
||||||
|
alias /app/media/;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, no-transform";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user