mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
feat: Add DISPATCHARR_ENV=modular support for multi-container deployments
- docker/entrypoint.sh: Conditional PostgreSQL init/startup for modular mode - docker/entrypoint.celery.sh: New dedicated entrypoint for celery container - prevents race condition in modular deployment - docker/uwsgi.modular.ini: New uWSGI config without Redis/Celery daemons - docker/Dockerfile: Add line ending fixes and chmod for entrypoints - adds cross-platform support for image builds - docker/docker-compose.yml: Configure modular mode with DISPATCHARR_ENV - uses new celery entrypoint and adds depends_on to prevent race condition
This commit is contained in:
parent
2fc2486c34
commit
3706e63bed
5 changed files with 133 additions and 23 deletions
|
|
@ -30,6 +30,10 @@ WORKDIR /app
|
|||
COPY . /app
|
||||
# Copy nginx configuration
|
||||
COPY ./docker/nginx.conf /etc/nginx/sites-enabled/default
|
||||
# Verify entrypoint scripts exist, fix line endings, and make them executable
|
||||
RUN ls -la /app/docker/entrypoint*.sh && \
|
||||
sed -i 's/\r$//' /app/docker/entrypoint.sh /app/docker/entrypoint.celery.sh /app/docker/entrypoint.aio.sh && \
|
||||
chmod +x /app/docker/entrypoint.sh /app/docker/entrypoint.celery.sh /app/docker/entrypoint.aio.sh
|
||||
# Clean out existing frontend folder
|
||||
RUN rm -rf /app/frontend
|
||||
# Copy built frontend assets
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ services:
|
|||
- db
|
||||
- redis
|
||||
environment:
|
||||
- DISPATCHARR_ENV=modular
|
||||
- POSTGRES_HOST=db
|
||||
- POSTGRES_DB=dispatcharr
|
||||
- POSTGRES_USER=dispatch
|
||||
|
|
@ -25,7 +26,6 @@ services:
|
|||
# Lower values = higher priority. Range: -20 (highest) to 19 (lowest)
|
||||
# Negative values require cap_add: SYS_NICE (uncomment below)
|
||||
#- UWSGI_NICE_LEVEL=-5 # uWSGI/FFmpeg/Streaming (default: 0, recommended: -5 for high priority)
|
||||
#- CELERY_NICE_LEVEL=5 # Celery/EPG/Background tasks (default: 5, low priority)
|
||||
#
|
||||
# Uncomment to enable high priority for streaming (required if UWSGI_NICE_LEVEL < 0)
|
||||
#cap_add:
|
||||
|
|
@ -52,22 +52,27 @@ services:
|
|||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
- web
|
||||
volumes:
|
||||
- ../:/app
|
||||
- ./data:/data
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
environment:
|
||||
- DISPATCHARR_ENV=modular
|
||||
- POSTGRES_HOST=db
|
||||
- POSTGRES_DB=dispatcharr
|
||||
- POSTGRES_USER=dispatch
|
||||
- POSTGRES_PASSWORD=secret
|
||||
- REDIS_HOST=redis
|
||||
- CELERY_BROKER_URL=redis://redis:6379/0
|
||||
command: >
|
||||
bash -c "
|
||||
cd /app &&
|
||||
nice -n 5 celery -A dispatcharr worker -l info
|
||||
"
|
||||
- DISPATCHARR_LOG_LEVEL=info
|
||||
#- CELERY_NICE_LEVEL=5 #Celery/EPG/Background tasks (default:5, low priority; Range: -20 to 19)
|
||||
- DJANGO_SETTINGS_MODULE=dispatcharr.settings
|
||||
- PYTHONUNBUFFERED=1
|
||||
# Uncomment to enable high priority for Celery (required if CELERY_NICE_LEVEL < 0)
|
||||
#cap_add:
|
||||
# - SYS_NICE
|
||||
entrypoint: ["/app/docker/entrypoint.celery.sh"]
|
||||
|
||||
db:
|
||||
image: postgres:14
|
||||
|
|
|
|||
22
docker/entrypoint.celery.sh
Normal file
22
docker/entrypoint.celery.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd /app
|
||||
source /dispatcharrpy/bin/activate
|
||||
|
||||
# Wait for Django secret key
|
||||
echo 'Waiting for Django secret key...'
|
||||
while [ ! -f /data/jwt ]; do sleep 1; done
|
||||
export DJANGO_SECRET_KEY=$(cat /data/jwt)
|
||||
|
||||
# Wait for migrations to complete
|
||||
echo 'Waiting for migrations to complete...'
|
||||
until python manage.py showmigrations 2>&1 | grep -q '\[X\]'; do
|
||||
echo 'Migrations not ready yet, waiting...'
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Start Celery
|
||||
echo 'Migrations complete, starting Celery...'
|
||||
celery -A dispatcharr beat -l info &
|
||||
nice -n ${CELERY_NICE_LEVEL:-5} celery -A dispatcharr worker -l info --autoscale=6,1
|
||||
|
|
@ -150,26 +150,43 @@ fi
|
|||
# Run init scripts
|
||||
echo "Starting user setup..."
|
||||
. /app/docker/init/01-user-setup.sh
|
||||
echo "Setting up PostgreSQL..."
|
||||
. /app/docker/init/02-postgres.sh
|
||||
|
||||
# Initialize PostgreSQL if NOT in modular mode (using external database)
|
||||
if [[ "$DISPATCHARR_ENV" != "modular" ]]; then
|
||||
echo "Setting up PostgreSQL..."
|
||||
. /app/docker/init/02-postgres.sh
|
||||
fi
|
||||
|
||||
echo "Starting init process..."
|
||||
. /app/docker/init/03-init-dispatcharr.sh
|
||||
|
||||
# Start PostgreSQL
|
||||
echo "Starting Postgres..."
|
||||
su - postgres -c "$PG_BINDIR/pg_ctl -D ${POSTGRES_DIR} start -w -t 300 -o '-c port=${POSTGRES_PORT}'"
|
||||
# Wait for PostgreSQL to be ready
|
||||
until su - postgres -c "$PG_BINDIR/pg_isready -h ${POSTGRES_HOST} -p ${POSTGRES_PORT}" >/dev/null 2>&1; do
|
||||
echo_with_timestamp "Waiting for PostgreSQL to be ready..."
|
||||
sleep 1
|
||||
done
|
||||
postgres_pid=$(su - postgres -c "$PG_BINDIR/pg_ctl -D ${POSTGRES_DIR} status" | sed -n 's/.*PID: \([0-9]\+\).*/\1/p')
|
||||
echo "✅ Postgres started with PID $postgres_pid"
|
||||
pids+=("$postgres_pid")
|
||||
# Start PostgreSQL if NOT in modular mode (using external database)
|
||||
if [[ "$DISPATCHARR_ENV" != "modular" ]]; then
|
||||
echo "Starting Postgres..."
|
||||
su - postgres -c "$PG_BINDIR/pg_ctl -D ${POSTGRES_DIR} start -w -t 300 -o '-c port=${POSTGRES_PORT}'"
|
||||
# Wait for PostgreSQL to be ready
|
||||
until su - postgres -c "$PG_BINDIR/pg_isready -h ${POSTGRES_HOST} -p ${POSTGRES_PORT}" >/dev/null 2>&1; do
|
||||
echo_with_timestamp "Waiting for PostgreSQL to be ready..."
|
||||
sleep 1
|
||||
done
|
||||
postgres_pid=$(su - postgres -c "$PG_BINDIR/pg_ctl -D ${POSTGRES_DIR} status" | sed -n 's/.*PID: \([0-9]\+\).*/\1/p')
|
||||
echo "✅ Postgres started with PID $postgres_pid"
|
||||
pids+=("$postgres_pid")
|
||||
else
|
||||
echo "🔗 Modular mode: Using external PostgreSQL at ${POSTGRES_HOST}:${POSTGRES_PORT}"
|
||||
# Wait for external PostgreSQL to be ready
|
||||
echo_with_timestamp "Waiting for external PostgreSQL to be ready..."
|
||||
until su - postgres -c "$PG_BINDIR/pg_isready -h ${POSTGRES_HOST} -p ${POSTGRES_PORT}" >/dev/null 2>&1; do
|
||||
echo_with_timestamp "Waiting for PostgreSQL at ${POSTGRES_HOST}:${POSTGRES_PORT}..."
|
||||
sleep 1
|
||||
done
|
||||
echo "✅ External PostgreSQL is ready"
|
||||
fi
|
||||
|
||||
# Ensure database encoding is UTF8
|
||||
. /app/docker/init/02-postgres.sh
|
||||
ensure_utf8_encoding
|
||||
# Ensure database encoding is UTF8 (only for internal database)
|
||||
if [[ "$DISPATCHARR_ENV" != "modular" ]]; then
|
||||
ensure_utf8_encoding
|
||||
fi
|
||||
|
||||
if [[ "$DISPATCHARR_ENV" = "dev" ]]; then
|
||||
. /app/docker/init/99-init-dev.sh
|
||||
|
|
@ -197,6 +214,9 @@ if [ "$DISPATCHARR_ENV" = "dev" ] && [ "$DISPATCHARR_DEBUG" != "true" ]; then
|
|||
elif [ "$DISPATCHARR_DEBUG" = "true" ]; then
|
||||
echo "🚀 Starting uwsgi in debug mode..."
|
||||
uwsgi_file="/app/docker/uwsgi.debug.ini"
|
||||
elif [ "$DISPATCHARR_ENV" = "modular" ]; then
|
||||
echo "🚀 Starting uwsgi in modular mode..."
|
||||
uwsgi_file="/app/docker/uwsgi.modular.ini"
|
||||
else
|
||||
echo "🚀 Starting uwsgi in production mode..."
|
||||
uwsgi_file="/app/docker/uwsgi.ini"
|
||||
|
|
|
|||
59
docker/uwsgi.modular.ini
Normal file
59
docker/uwsgi.modular.ini
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
[uwsgi]
|
||||
; Modular deployment mode - external PostgreSQL, Redis, and Celery
|
||||
; Remove file creation commands since we're not logging to files anymore
|
||||
; exec-pre = mkdir -p /data/logs
|
||||
; exec-pre = touch /data/logs/uwsgi.log
|
||||
; exec-pre = chmod 666 /data/logs/uwsgi.log
|
||||
|
||||
; First run Redis availability check script once
|
||||
exec-pre = python /app/scripts/wait_for_redis.py
|
||||
|
||||
; Start Daphne for WebSocket support (required for real-time features)
|
||||
; Redis and Celery run in separate containers in modular mode
|
||||
attach-daemon = daphne -b 0.0.0.0 -p 8001 dispatcharr.asgi:application
|
||||
|
||||
# Core settings
|
||||
chdir = /app
|
||||
module = dispatcharr.wsgi:application
|
||||
virtualenv = /dispatcharrpy
|
||||
master = true
|
||||
env = DJANGO_SETTINGS_MODULE=dispatcharr.settings
|
||||
env = USE_NGINX_ACCEL=true
|
||||
socket = /app/uwsgi.sock
|
||||
chmod-socket = 777
|
||||
vacuum = true
|
||||
die-on-term = true
|
||||
static-map = /static=/app/static
|
||||
|
||||
# Worker management
|
||||
workers = 4
|
||||
|
||||
# Optimize for streaming
|
||||
http = 0.0.0.0:5656
|
||||
http-keepalive = 1
|
||||
buffer-size = 65536 # Increase buffer for large payloads
|
||||
post-buffering = 4096 # Reduce buffering for real-time streaming
|
||||
http-timeout = 600 # Prevent disconnects from long streams
|
||||
socket-timeout = 600 # Prevent write timeouts when client buffers
|
||||
lazy-apps = true # Improve memory efficiency
|
||||
|
||||
# Async mode (use gevent for high concurrency)
|
||||
gevent = 400 # Each unused greenlet costs ~2-4KB of memory
|
||||
# Higher values have minimal performance impact when idle, but provide capacity for traffic spikes
|
||||
# If memory usage becomes an issue, reduce this value
|
||||
|
||||
# Performance tuning
|
||||
thunder-lock = true
|
||||
log-4xx = true
|
||||
log-5xx = true
|
||||
disable-logging = false
|
||||
|
||||
# Logging configuration
|
||||
# Enable console logging (stdout)
|
||||
log-master = true
|
||||
# Enable strftime formatting for timestamps
|
||||
logformat-strftime = true
|
||||
log-date = %%Y-%%m-%%d %%H:%%M:%%S,000
|
||||
# Use formatted time with environment variable for log level
|
||||
log-format = %(ftime) $(DISPATCHARR_LOG_LEVEL) uwsgi.requests Worker ID: %(wid) %(method) %(status) %(uri) %(msecs)ms
|
||||
log-buffering = 1024 # Add buffer size limit for logging
|
||||
Loading…
Add table
Add a link
Reference in a new issue