django and fastapi apps
This commit is contained in:
21
ctrl/.env.template
Normal file
21
ctrl/.env.template
Normal 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
14
ctrl/Dockerfile
Normal 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
61
ctrl/README.md
Normal 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
76
ctrl/deploy.sh
Executable 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
128
ctrl/docker-compose.yml
Normal 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
84
ctrl/nginx.conf
Normal 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
33
ctrl/run.sh
Executable 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 "$@"
|
||||
Reference in New Issue
Block a user