diff --git a/docker/Dockerfile b/docker/Dockerfile index 1a011943..b7fc0dcf 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,9 +7,13 @@ ENV PATH="/dispatcharrpy/bin:$PATH" \ RUN apt-get update && \ apt-get install -y --no-install-recommends \ + build-essential \ curl \ gcc \ git \ + libpcre3 \ + libpcre3-dev \ + python3-dev \ wget && \ echo "=== setting up nodejs ===" && \ curl -sL https://deb.nodesource.com/setup_23.x -o /tmp/nodesource_setup.sh && \ @@ -20,6 +24,7 @@ RUN apt-get update && \ python -m pip install virtualenv && \ virtualenv /dispatcharrpy && \ git clone https://github.com/Dispatcharr/Dispatcharr /app && \ + git checkout --track origin/uwsgi && \ cd /app && \ pip install --no-cache-dir -r requirements.txt && \ python manage.py collectstatic --noinput && \ @@ -45,6 +50,7 @@ RUN apt-get update && \ ffmpeg \ gnupg2 \ gpg \ + libpcre3 \ libpq-dev \ lsb-release \ nginx \ diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 35b30142..8a5ac8c1 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -27,227 +27,56 @@ 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 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" -echo_with_timestamp "POSTGRES_PASSWORD: $POSTGRES_PASSWORD" -echo_with_timestamp "POSTGRES_HOST: $POSTGRES_HOST" -echo_with_timestamp "POSTGRES_PORT: $POSTGRES_PORT" - -# Create group if it doesn't exist -if ! getent group "$PGID" >/dev/null 2>&1; then - groupadd -g "$PGID" mygroup -fi -# Create user if it doesn't exist -if ! getent passwd $PUID > /dev/null 2>&1; then - useradd -u $PUID -g $PGID -m $POSTGRES_USER -else - existing_user=$(getent passwd $PUID | cut -d: -f1) - if [ "$existing_user" != "$POSTGRES_USER" ]; then - usermod -l $POSTGRES_USER -g $PGID "$existing_user" - fi +# Global variables, stored so other users inherit them +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 + echo "export POSTGRES_DB=$POSTGRES_DB" >> /etc/profile.d/dispatcharr.sh + echo "export POSTGRES_USER=$POSTGRES_USER" >> /etc/profile.d/dispatcharr.sh + echo "export POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> /etc/profile.d/dispatcharr.sh + echo "export POSTGRES_HOST=$POSTGRES_HOST" >> /etc/profile.d/dispatcharr.sh + echo "export POSTGRES_PORT=$POSTGRES_PORT" >> /etc/profile.d/dispatcharr.sh fi -# If running in development mode, install and start frontend -if [ "$DISPATCHARR_ENV" = "dev" ]; then - echo "🚀 Development Mode - Setting up Frontend..." +chmod +x /etc/profile.d/dispatcharr.sh - # Install Node.js - echo "=== setting up nodejs ===" - curl -sL https://deb.nodesource.com/setup_23.x -o /tmp/nodesource_setup.sh - bash /tmp/nodesource_setup.sh - apt-get update - apt-get install -y --no-install-recommends \ - nodejs +# Run init scripts +bash /app/docker/init/01-user-setup.sh +bash /app/docker/init/02-postgres.sh - # Install frontend dependencies - cd /app/frontend && npm install - cd /app +# Start PostgreSQL +echo "Starting Postgres..." +su - postgres -c "/usr/lib/postgresql/14/bin/pg_ctl -D /data start -w -t 300 -o '-c port=${POSTGRES_PORT}'" +# Wait for PostgreSQL to be ready +until su - postgres -c "/usr/lib/postgresql/14/bin/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 "/usr/lib/postgresql/14/bin/pg_ctl -D /data status" | sed -n 's/.*PID: \([0-9]\+\).*/\1/p') +echo "✅ Postgres started with PID $postgres_pid" +pids+=("$postgres_pid") - # Start React development server - echo "🚀 Starting React Dev Server..." - cd /app/frontend - su - $POSTGRES_USER -c "cd /app/frontend && /app/frontend/node_modules/pm2/bin/pm2 --name dev-server start npm -- run 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 -else - echo "🚀 Starting nginx..." - nginx - nginx_pid=$(pgrep nginx | sort | head -n1) - echo "✅ nginx started with PID $nginx_pid" - pids+=("$nginx_pid") -fi +echo "🚀 Starting nginx..." +nginx +nginx_pid=$(pgrep nginx | sort | head -n1) +echo "✅ nginx started with PID $nginx_pid" +pids+=("$nginx_pid") -# 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'..." +echo "🚀 Starting uwsgi..." +su - $POSTGRES_USER -c "cd /app && uwsgi --ini /app/docker/uwsgi.ini &" +uwsgi_pid=$(pgrep uwsgi | sort | head -n1) +echo "✅ uwsgi started with PID $uwsgi_pid" +pids+=("$uwsgi_pid") - # 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" - - # 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 - - # Start Redis - echo "🚀 Starting Redis..." - su - $POSTGRES_USER -c "redis-server --daemonize no &" - sleep 1 # Give Redis time to start - redis_pid=$(pgrep -x redis-server) - if [ -n "$redis_pid" ]; then - echo "✅ Redis started with PID $redis_pid" - pids+=("$redis_pid") - else - echo "❌ Redis failed to start!" - fi - - # Start Celery - echo "🚀 Starting Celery..." - su - $POSTGRES_USER -c "cd /app && celery -A dispatcharr worker -l info &" - celery_pid=$(pgrep -x celery) - echo "✅ Celery started with PID $celery_pid" - pids+=("$celery_pid") - - # Start PostgreSQL - echo "Starting Postgres..." - su - postgres -c "$PG_BINDIR/pg_ctl -D $PGDATA 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 $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." - fi -fi - -# Run Django commands -cd /app -echo_with_timestamp "Running Django commands..." -python manage.py migrate --noinput || true -python manage.py collectstatic --noinput || true - -# 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") - -# 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..." diff --git a/docker/init/01-user-setup.sh b/docker/init/01-user-setup.sh new file mode 100644 index 00000000..43878903 --- /dev/null +++ b/docker/init/01-user-setup.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Set up user details +export PUID=${PUID:-1000} +export PGID=${PGID:-1000} + +# Create group if it doesn't exist +if ! getent group "$PGID" >/dev/null 2>&1; then + groupadd -g "$PGID" mygroup +fi +# Create user if it doesn't exist +if ! getent passwd $PUID > /dev/null 2>&1; then + useradd -u $PUID -g $PGID -m $POSTGRES_USER +else + existing_user=$(getent passwd $PUID | cut -d: -f1) + if [ "$existing_user" != "$POSTGRES_USER" ]; then + usermod -l $POSTGRES_USER -g $PGID "$existing_user" + fi +fi diff --git a/docker/init/02-postgres.sh b/docker/init/02-postgres.sh new file mode 100644 index 00000000..36c76270 --- /dev/null +++ b/docker/init/02-postgres.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Inwitialize PostgreSQL database +if [ -z "$(ls -A "/data")" ]; then + echo_with_timestamp "Initializing PostgreSQL database..." + mkdir -p "/data" + chown -R postgres:postgres "/data" + chmod 700 "/data" + + # Initialize PostgreSQL + su - postgres -c "/usr/lib/postgresql/14/bin/initdb -D /data" + # Configure PostgreSQL + echo "host all all 0.0.0.0/0 md5" >> "/data/pg_hba.conf" + echo "listen_addresses='*'" >> "/data/postgresql.conf" + + # Start PostgreSQL + echo "Starting Postgres..." + su - postgres -c "/usr/lib/postgresql/14/bin/pg_ctl -D /data start -w -t 300 -o '-c port=${POSTGRES_PORT}'" + # Wait for PostgreSQL to be ready + until su - postgres -c "/usr/lib/postgresql/14/bin/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 "/usr/lib/postgresql/14/bin/pg_ctl -D /data status" | sed -n 's/.*PID: \([0-9]\+\).*/\1/p') + + # 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}" <