diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 0be3f429..e3a1f7d5 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,23 +1,64 @@ -#!/bin/sh +#!/bin/bash set -e # Exit immediately if a command exits with a non-zero status +# Function to clean up only running processes +cleanup() { + echo "🔥 Cleanup triggered! Stopping services..." + for pid in "${pids[@]}"; do + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + echo "⛔ Stopping process (PID: $pid)..." + kill -TERM "$pid" 2>/dev/null + else + echo "✅ Process (PID: $pid) already stopped." + fi + done + wait +} + +# Catch termination signals (CTRL+C, Docker Stop, etc.) +trap cleanup TERM INT + +# Initialize an array to store PIDs +pids=() + # Function to echo with timestamp echo_with_timestamp() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" } +# Global variables +if [[ ! -f /etc/profile.d/dispatcharr.sh ]]; then + echo "export PATH=$PATH" >> /etc/profile.d/dispatcharr.sh + echo "export VIRTUAL_ENV=$VIRTUAL_ENV" >> /etc/profile.d/dispatcharr.sh + echo "export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE" >> /etc/profile.d/dispatcharr.sh + echo "export PYTHONUNBUFFERED=$PYTHONUNBUFFERED" >> /etc/profile.d/dispatcharr.sh +fi + +chmod +x /etc/profile.d/dispatcharr.sh + +# Dispatcharr variables +export ADMIN_PORT=5656 + # Set PostgreSQL environment variables export POSTGRES_DB=${POSTGRES_DB:-dispatcharr} export POSTGRES_USER=${POSTGRES_USER:-dispatch} export POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-secret} export POSTGRES_HOST=${POSTGRES_HOST:-localhost} export POSTGRES_PORT=${POSTGRES_PORT:-5432} -export PUID=${PUID:-1000} -export PGID=${PGID:-1000} export PGDATA=${PGDATA:-/app/data/db} export PG_BINDIR="/usr/lib/postgresql/14/bin" +# Set up user details +export PUID=${PUID:-1000} +export PGID=${PGID:-1000} + +# Set up initial django admin +export DJANGO_SUPERUSER_USERNAME=${DEFAULT_USERNAME:-admin} +export DJANGO_SUPERUSER_PASSWORD=${DEFAULT_PASSWORD:-admin} +export DJANGO_SUPERUSER_EMAIL=${DEFAULT_EMAIL:-admin@dispatcharr.local} + + # Echo environment variables for debugging echo_with_timestamp "POSTGRES_DB: $POSTGRES_DB" echo_with_timestamp "POSTGRES_USER: $POSTGRES_USER" @@ -39,38 +80,86 @@ else fi fi -# Initialize PostgreSQL database -if [ -z "$(ls -A "$PGDATA")" ]; then - echo_with_timestamp "Initializing PostgreSQL database..." - mkdir -p "$PGDATA" - chown -R postgres:postgres "$PGDATA" - chmod 700 "$PGDATA" +# If running in development mode, install and start frontend +if [ "$DISPATCHARR_ENV" = "dev" ]; then + echo "🚀 Development Mode - Setting up Frontend..." - # Initialize PostgreSQL - su - postgres -c "$PG_BINDIR/initdb -D $PGDATA" - # Configure PostgreSQL - echo "host all all 0.0.0.0/0 md5" >> "$PGDATA/pg_hba.conf" - echo "listen_addresses='*'" >> "$PGDATA/postgresql.conf" + # Install Node.js + apt-get update && apt-get install -y nodejs + + # Install frontend dependencies + cd /app/frontend && npm install + cd /app + + # Start React development server + echo "🚀 Starting React Dev Server..." + cd /app/frontend + su - $POSTGRES_USER -c "PORT=9191 /app/frontend/node_modules/pm2/bin/pm2 --name dev-server start npm -- start" + ./node_modules/pm2/bin/pm2 logs & + react_pid=$(cat /home/dispatch/.pm2/pids/dev-server*) + echo "✅ React started with PID $react_pid" + pids+=("$react_pid") + cd /app fi -# Start PostgreSQL -su - postgres -c "$PG_BINDIR/pg_ctl -D $PGDATA start -w -t 300 -o '-c port=${POSTGRES_PORT}'" +# If running in `dev` or `aio`, start Postgres, Redis, and Celery +if [ "$DISPATCHARR_ENV" = "dev" ] || [ "$DISPATCHARR_ENV" = "aio" ]; then + echo "🚀 Running Postgres, Redis, and Celery for '$DISPATCHARR_ENV'..." -# 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 + # Initialize PostgreSQL database + if [ -z "$(ls -A "$PGDATA")" ]; then + echo_with_timestamp "Initializing PostgreSQL database..." + mkdir -p "$PGDATA" + chown -R postgres:postgres "$PGDATA" + chmod 700 "$PGDATA" -# Setup database if needed -if ! su - postgres -c "psql -p ${POSTGRES_PORT} -tAc \"SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB';\"" | grep -q 1; then - # Create PostgreSQL database - echo_with_timestamp "Creating PostgreSQL database..." - su - postgres -c "createdb -p ${POSTGRES_PORT} ${POSTGRES_DB}" + # Initialize PostgreSQL + su - postgres -c "$PG_BINDIR/initdb -D $PGDATA" + # Configure PostgreSQL + echo "host all all 0.0.0.0/0 md5" >> "$PGDATA/pg_hba.conf" + echo "listen_addresses='*'" >> "$PGDATA/postgresql.conf" + fi - # Create user, set ownership, and grant privileges - echo_with_timestamp "Creating PostgreSQL user..." - su - postgres -c "psql -p ${POSTGRES_PORT} -d ${POSTGRES_DB}" </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 $PGDATA status" | sed -n 's/.*PID: \([0-9]\+\).*/\1/p') + echo "✅ Postgres started with PID $postgres_pid" + pids+=("$postgres_pid") + + # Setup database if needed + if ! su - postgres -c "psql -p ${POSTGRES_PORT} -tAc \"SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB';\"" | grep -q 1; then + # Create PostgreSQL database + echo_with_timestamp "Creating PostgreSQL database..." + su - postgres -c "createdb -p ${POSTGRES_PORT} ${POSTGRES_DB}" + + # Create user, set ownership, and grant privileges + echo_with_timestamp "Creating PostgreSQL user..." + su - postgres -c "psql -p ${POSTGRES_PORT} -d ${POSTGRES_DB}" </dev/null 2>&1; then - echo_with_timestamp "ERROR: PostgreSQL is running but the database is not accessible. Exiting..." - exit 1 -else - echo_with_timestamp "PostgreSQL database is accessible." + # Verify database accessibility + echo_with_timestamp "Verifying database accessibility..." + if ! su - $POSTGRES_USER -c "psql -p ${POSTGRES_PORT} -d ${POSTGRES_DB} -c 'SELECT 1;'" >/dev/null 2>&1; then + echo_with_timestamp "ERROR: PostgreSQL is running but the database is not accessible. Exiting..." + exit 1 + else + echo_with_timestamp "PostgreSQL database is accessible." + fi fi -# Start Redis -echo_with_timestamp "Starting Redis..." -su - $POSTGRES_USER -c 'redis-server --daemonize yes' - # Run Django commands +cd /app echo_with_timestamp "Running Django commands..." -python manage.py collectstatic --noinput || true -python manage.py makemigrations --noinput || true python manage.py migrate --noinput || true -python manage.py collectstatic --noinput || true +echo_with_timestamp "Checking if Django superuser exists..." +if ! python manage.py shell -c "from django.contrib.auth import get_user_model; exit(0) if get_user_model().objects.filter(username='${DJANGO_SUPERUSER_USERNAME}').exists() else exit(1)"; then + echo_with_timestamp "Superuser does not exist. Creating..." + python manage.py createsuperuser --noinput || true +else + echo_with_timestamp "Superuser already exists. Skipping creation." +fi -# Start Celery -echo_with_timestamp "Starting Celery..." -su - $POSTGRES_USER -c 'cd /app && celery -A dispatcharr worker --loglevel=info &' +# Always start Gunicorn +echo "🚀 Starting Gunicorn..." +su - $POSTGRES_USER -c "cd /app && gunicorn --workers=4 --worker-class=gevent --timeout=300 --bind 0.0.0.0:${ADMIN_PORT} dispatcharr.wsgi:application &" +gunicorn_pid=$(pgrep -x gunicorn | sort | head -n1) +echo "✅ Gunicorn started with PID $gunicorn_pid" +pids+=("$gunicorn_pid") -# Start Gunicorn -echo_with_timestamp "Starting Gunicorn..." -su - $POSTGRES_USER -c 'cd /app && gunicorn --workers=4 --worker-class=gevent --timeout=300 --bind 0.0.0.0:9191 dispatcharr.wsgi:application' +echo "🚀 Starting nginx..." +nginx +nginx_pid=$(pgrep nginx | sort | head -n1) +echo "✅ nginx started with PID $nginx_pid" +pids+=("$nginx_pid") + +# Log PIDs +echo "📝 Process PIDs: ${pids[*]}" + +echo " + + %%%% + %%%%%%%%%%% + %%%%%%%%%%%%%%% + %%%% %%%%%%%%%% + %%%%% %%%%%%%%%% + @%%%% %%%%%%%%%% + %%%% * %%%%%%%%%% + %%%% **** %%%%%%%%%% + %%%% ******* %%%%%%%% + %%%% *********** %%%%%% + %%%% ************** %%%% + %%%% ************* % + %%%% ********** @%%% % + %%%% ******* %%%%%% + %%%% **** %%%%%%%%%% + %%%% %%%%%%%%%% + %%%% %%%%%%%%%% + %%%% %%%%%%%%% + %%%% %%%%%%%%%@ + %%%%%%%%% + @%%%%%%%%%% + %%%% + +DISPACTHARR HAS SUCCESSFULLY STARTED +" +# Wait for at least one process to exit and log the process that exited first +if [ ${#pids[@]} -gt 0 ]; then + echo "⏳ Waiting for processes to exit..." + while kill -0 "${pids[@]}" 2>/dev/null; do + sleep 1 # Wait for a second before checking again + done + + echo "🚨 One of the processes exited! Checking which one..." + + for pid in "${pids[@]}"; do + if ! kill -0 "$pid" 2>/dev/null; then + process_name=$(ps -p "$pid" -o comm=) + echo "❌ Process $process_name (PID: $pid) has exited!" + fi + done +else + echo "❌ No processes started. Exiting." + exit 1 +fi + +# Cleanup and stop remaining processes +cleanup