django and fastapi apps

This commit is contained in:
2026-02-03 12:20:40 -03:00
parent d31a3ed612
commit 67573713bd
54 changed files with 3272 additions and 11 deletions

21
ctrl/.env.template Normal file
View File

@@ -0,0 +1,21 @@
# MPR Control Environment
# Copy to .env and adjust values
# Database
POSTGRES_DB=mpr
POSTGRES_USER=mpr_user
POSTGRES_PASSWORD=mpr_pass
# Ports (less common to avoid conflicts)
POSTGRES_PORT=5433
REDIS_PORT=6380
DJANGO_PORT=8701
FASTAPI_PORT=8702
TIMELINE_PORT=5173
# Worker
MPR_EXECUTOR=local
# Remote deployment (optional)
# SERVER=user@host
# REMOTE_PATH=~/mpr

14
ctrl/Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

61
ctrl/README.md Normal file
View File

@@ -0,0 +1,61 @@
# MPR Control
Scripts for running and deploying MPR.
## Setup
1. Add to `/etc/hosts`:
```
127.0.0.1 mpr.local.ar
```
2. Copy environment template:
```bash
cp ctrl/.env.template ctrl/.env
```
3. Start the stack:
```bash
./ctrl/run.sh
```
## URLs
- http://mpr.local.ar/admin - Django Admin
- http://mpr.local.ar/api/docs - FastAPI Swagger
- http://mpr.local.ar/ui - Timeline UI
## Commands
```bash
# Start all services
./ctrl/run.sh
# Start in detached mode
./ctrl/run.sh -d
# Rebuild and start
./ctrl/run.sh --build
# Stop all
./ctrl/run.sh down
# View logs
./ctrl/run.sh logs -f
# Deploy to remote (configure SERVER/REMOTE_PATH in .env)
./ctrl/deploy.sh
./ctrl/deploy.sh --restart
./ctrl/deploy.sh --dry-run
```
## Ports
| Service | Internal | External |
|------------|----------|----------|
| nginx | 80 | 80 |
| Django | 8701 | 8701 |
| FastAPI | 8702 | 8702 |
| Timeline | 5173 | 5173 |
| PostgreSQL | 5432 | 5433 |
| Redis | 6379 | 6380 |

76
ctrl/deploy.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Deploy MPR to remote server via rsync
# Uses project .gitignore for excludes
#
# Usage: ./ctrl/deploy.sh [--restart] [--dry-run]
#
# Examples:
# ./ctrl/deploy.sh # Sync files only
# ./ctrl/deploy.sh --restart # Sync and restart services
# ./ctrl/deploy.sh --dry-run # Preview sync
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "$SCRIPT_DIR/.env" 2>/dev/null || true
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ -z "$SERVER" ] || [ -z "$REMOTE_PATH" ]; then
echo -e "${RED}Error: SERVER and REMOTE_PATH must be set in ctrl/.env${NC}"
echo "Example:"
echo " SERVER=user@host"
echo " REMOTE_PATH=~/mpr"
exit 1
fi
RESTART=false
DRY_RUN=""
while [ $# -gt 0 ]; do
case "$1" in
--restart)
RESTART=true
shift
;;
--dry-run)
DRY_RUN="--dry-run"
shift
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
echo -e "${GREEN}=== Deploying MPR to $SERVER:$REMOTE_PATH ===${NC}"
# Sync files using .gitignore for excludes
echo -e "${YELLOW}Syncing files...${NC}"
rsync -avz --delete $DRY_RUN \
--filter=':- .gitignore' \
--exclude='.git' \
--exclude='media/*' \
--exclude='ctrl/.env' \
"$PROJECT_ROOT/" "$SERVER:$REMOTE_PATH/"
if [ -n "$DRY_RUN" ]; then
echo -e "${YELLOW}Dry run - no changes made${NC}"
exit 0
fi
# Copy env template if .env doesn't exist on remote
ssh "$SERVER" "[ -f $REMOTE_PATH/ctrl/.env ] || cp $REMOTE_PATH/ctrl/.env.template $REMOTE_PATH/ctrl/.env"
if [ "$RESTART" = true ]; then
echo -e "${YELLOW}Restarting services...${NC}"
ssh "$SERVER" "cd $REMOTE_PATH/ctrl && docker compose down && docker compose up -d --build"
fi
echo -e "${GREEN}Done!${NC}"

128
ctrl/docker-compose.yml Normal file
View File

@@ -0,0 +1,128 @@
x-common-env: &common-env
DATABASE_URL: postgresql://mpr_user:mpr_pass@postgres:5432/mpr
REDIS_URL: redis://redis:6379/0
DJANGO_SETTINGS_MODULE: mpr.settings
DEBUG: 1
x-healthcheck-defaults: &healthcheck-defaults
interval: 5s
timeout: 5s
retries: 5
services:
# =============================================================================
# Infrastructure
# =============================================================================
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: mpr
POSTGRES_USER: mpr_user
POSTGRES_PASSWORD: mpr_pass
ports:
- "5433:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
<<: *healthcheck-defaults
test: ["CMD-SHELL", "pg_isready -U mpr_user -d mpr"]
redis:
image: redis:7-alpine
ports:
- "6380:6379"
volumes:
- redis-data:/data
healthcheck:
<<: *healthcheck-defaults
test: ["CMD", "redis-cli", "ping"]
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ../media:/app/media:ro
depends_on:
- django
- fastapi
- timeline
# =============================================================================
# Application Services
# =============================================================================
django:
build:
context: ..
dockerfile: ctrl/Dockerfile
command: >
bash -c "python manage.py migrate &&
python manage.py loadbuiltins || true &&
python manage.py runserver 0.0.0.0:8701"
ports:
- "8701:8701"
environment:
<<: *common-env
volumes:
- ..:/app
- ../media:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
fastapi:
build:
context: ..
dockerfile: ctrl/Dockerfile
command: uvicorn api.main:app --host 0.0.0.0 --port 8702 --reload
ports:
- "8702:8702"
environment:
<<: *common-env
volumes:
- ..:/app
- ../media:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
celery:
build:
context: ..
dockerfile: ctrl/Dockerfile
command: celery -A mpr worker -l info -Q default -c 2
environment:
<<: *common-env
MPR_EXECUTOR: local
volumes:
- ..:/app
- ../media:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
timeline:
build:
context: ../ui/timeline
dockerfile: Dockerfile
ports:
- "5173:5173"
volumes:
- ../ui/timeline/src:/app/src
volumes:
postgres-data:
redis-data:
networks:
default:
name: mpr

84
ctrl/nginx.conf Normal file
View File

@@ -0,0 +1,84 @@
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
upstream django {
server django:8701;
}
upstream fastapi {
server fastapi:8702;
}
upstream timeline {
server timeline:5173;
}
server {
listen 80;
server_name mpr.local.ar;
# Django Admin
location /admin {
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;
}
# Django static files
location /static {
proxy_pass http://django;
proxy_set_header Host $host;
}
# FastAPI
location /api {
proxy_pass http://fastapi;
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;
}
# Timeline UI
location /ui {
proxy_pass http://timeline;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Vite HMR websocket
location /@vite {
proxy_pass http://timeline;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# Media files
location /media {
alias /app/media;
autoindex on;
}
# Default to Timeline UI
location / {
proxy_pass http://timeline;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}

33
ctrl/run.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
# Run MPR stack locally
# Usage: ./ctrl/run.sh [docker-compose args]
#
# Examples:
# ./ctrl/run.sh # Start all services
# ./ctrl/run.sh --build # Rebuild and start
# ./ctrl/run.sh -d # Detached mode
# ./ctrl/run.sh down # Stop all
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Load env
if [ -f .env ]; then
set -a
source .env
set +a
else
echo "Warning: .env not found, using defaults"
echo "Copy .env.template to .env to customize"
fi
# Check /etc/hosts
if ! grep -q "mpr.local.ar" /etc/hosts 2>/dev/null; then
echo "Note: Add to /etc/hosts:"
echo " 127.0.0.1 mpr.local.ar"
echo ""
fi
docker compose "$@"