From 236b2307e1e7878ddb2a2bb67ea4ede7312479cd Mon Sep 17 00:00:00 2001 From: Matt Grutza Date: Wed, 21 Jan 2026 17:40:36 -0600 Subject: [PATCH] Add health check and fix dangerous checks - docker-compose: added service health checks - dockerfile: added if logic for sed command so missing files do not cause build fail - entrypoint.celery: change migration detection to not continue until ALL migrations are applied - entrypoint: trim django key and change external postgres check to python in case postgres binaries are missing --- docker/Dockerfile | 10 ++++++---- docker/docker-compose.yml | 25 ++++++++++++++++++++----- docker/entrypoint.celery.sh | 6 +++--- docker/entrypoint.sh | 17 ++++++++++++++--- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 409f1096..3e30a825 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -30,10 +30,12 @@ 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 +# Fix line endings and make entrypoint scripts executable +RUN for f in /app/docker/entrypoint*.sh; do \ + if [ -f "$f" ]; then \ + sed -i 's/\r$//' "$f" && chmod +x "$f"; \ + fi; \ + done # Clean out existing frontend folder RUN rm -rf /app/frontend # Copy built frontend assets diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index df295f90..e9254d30 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -7,8 +7,10 @@ services: volumes: - ./data:/data depends_on: - - db - - redis + db: + condition: service_healthy + redis: + condition: service_healthy environment: - DISPATCHARR_ENV=modular - POSTGRES_HOST=db @@ -50,9 +52,12 @@ services: image: ghcr.io/dispatcharr/dispatcharr:latest container_name: dispatcharr_celery depends_on: - - db - - redis - - web + db: + condition: service_healthy + redis: + condition: service_healthy + web: + condition: service_started volumes: - ./data:/data extra_hosts: @@ -85,10 +90,20 @@ services: - POSTGRES_PASSWORD=secret volumes: - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U dispatch -d dispatcharr"] + interval: 5s + timeout: 5s + retries: 5 redis: image: redis:latest container_name: dispatcharr_redis + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 volumes: postgres_data: diff --git a/docker/entrypoint.celery.sh b/docker/entrypoint.celery.sh index fafe2c3f..0516cc54 100644 --- a/docker/entrypoint.celery.sh +++ b/docker/entrypoint.celery.sh @@ -7,11 +7,11 @@ 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) +export DJANGO_SECRET_KEY="$(tr -d '\r\n' < /data/jwt)" -# Wait for migrations to complete +# Wait for migrations to complete (check that NO unapplied migrations remain) echo 'Waiting for migrations to complete...' -until python manage.py showmigrations 2>&1 | grep -q '\[X\]'; do +until ! python manage.py showmigrations 2>&1 | grep -q '\[ \]'; do echo 'Migrations not ready yet, waiting...' sleep 2 done diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 36948c1f..0c17b9d0 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -66,7 +66,7 @@ PY mv -f "$tmpfile" "$SECRET_FILE" || { echo "move failed"; rm -f "$tmpfile"; exit 1; } umask $old_umask fi -export DJANGO_SECRET_KEY="$(cat "$SECRET_FILE")" +export DJANGO_SECRET_KEY="$(tr -d '\r\n' < "$SECRET_FILE")" # Process priority configuration # UWSGI_NICE_LEVEL: Absolute nice value for uWSGI/streaming (default: 0 = normal priority) @@ -174,9 +174,20 @@ if [[ "$DISPATCHARR_ENV" != "modular" ]]; then pids+=("$postgres_pid") else echo "🔗 Modular mode: Using external PostgreSQL at ${POSTGRES_HOST}:${POSTGRES_PORT}" - # Wait for external PostgreSQL to be ready + # Wait for external PostgreSQL to be ready using Python (no pg_isready needed) 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 + until python3 -c " +import socket +import sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(2) + s.connect(('${POSTGRES_HOST}', ${POSTGRES_PORT})) + s.close() + sys.exit(0) +except Exception: + sys.exit(1) +" 2>/dev/null; do echo_with_timestamp "Waiting for PostgreSQL at ${POSTGRES_HOST}:${POSTGRES_PORT}..." sleep 1 done