From addb2ad1eb39ffcafe5074f72642a823b258ab6a Mon Sep 17 00:00:00 2001 From: "architect.in.git" Date: Tue, 18 Mar 2025 21:00:56 -0600 Subject: [PATCH] separated containers --- Dockerfile | 1 - app.py | 74 +++++++++++++++++++++++++++++++---- docker-compose.yaml | 21 +++++++++- entrypoint.sh | 27 +------------ routes/utils/celery_config.py | 11 ++++-- 5 files changed, 94 insertions(+), 40 deletions(-) diff --git a/Dockerfile b/Dockerfile index 848ad61..f53b86b 100755 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ gosu \ git \ - redis-server \ ffmpeg \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/app.py b/app.py index d575c64..786231f 100755 --- a/app.py +++ b/app.py @@ -15,10 +15,13 @@ from pathlib import Path import os import atexit import sys +import redis +import socket # Import Celery configuration and manager from routes.utils.celery_tasks import celery_app from routes.utils.celery_manager import celery_manager +from routes.utils.celery_config import REDIS_URL # Configure application-wide logging def setup_logging(): @@ -71,6 +74,56 @@ def setup_logging(): # Return the main file handler for permissions adjustment return file_handler +def check_redis_connection(): + """Check if Redis is reachable and retry with exponential backoff if not""" + max_retries = 5 + retry_count = 0 + retry_delay = 1 # start with 1 second + + # Extract host and port from REDIS_URL + redis_host = "redis" # default + redis_port = 6379 # default + + # Parse from REDIS_URL if possible + if REDIS_URL and "://" in REDIS_URL: + parts = REDIS_URL.split("://")[1].split(":") + if len(parts) >= 2: + redis_host = parts[0] + redis_port = int(parts[1].split("/")[0]) + + # Log Redis connection details + logging.info(f"Checking Redis connection to {redis_host}:{redis_port}") + + while retry_count < max_retries: + try: + # First try socket connection to check if Redis port is open + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(2) + result = sock.connect_ex((redis_host, redis_port)) + sock.close() + + if result != 0: + raise ConnectionError(f"Cannot connect to Redis at {redis_host}:{redis_port}") + + # If socket connection successful, try Redis ping + r = redis.Redis.from_url(REDIS_URL) + r.ping() + logging.info("Successfully connected to Redis") + return True + except Exception as e: + retry_count += 1 + if retry_count >= max_retries: + logging.error(f"Failed to connect to Redis after {max_retries} attempts: {e}") + logging.error(f"Make sure Redis is running at {redis_host}:{redis_port}") + return False + + logging.warning(f"Redis connection attempt {retry_count} failed: {e}") + logging.info(f"Retrying in {retry_delay} seconds...") + time.sleep(retry_delay) + retry_delay *= 2 # exponential backoff + + return False + def create_app(): app = Flask(__name__) @@ -169,11 +222,16 @@ if __name__ == '__main__': # Log application startup logging.info("=== Spotizerr Application Starting ===") - # Start Celery workers - start_celery_workers() - - # Create and start Flask app - app = create_app() - logging.info("Starting Flask server on port 7171") - from waitress import serve - serve(app, host='0.0.0.0', port=7171) + # Check Redis connection before starting workers + if check_redis_connection(): + # Start Celery workers + start_celery_workers() + + # Create and start Flask app + app = create_app() + logging.info("Starting Flask server on port 7171") + from waitress import serve + serve(app, host='0.0.0.0', port=7171) + else: + logging.error("Cannot start application: Redis connection failed") + sys.exit(1) diff --git a/docker-compose.yaml b/docker-compose.yaml index d7d0d24..3d21707 100755 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -16,5 +16,22 @@ services: - PUID=1000 # Replace with your desired user ID | Remove both if you want to run as root (not recommended, might result in unreadable files) - PGID=1000 # Replace with your desired group ID | The user must have write permissions in the volume mapped to /app/downloads - UMASK=0022 # Optional: Sets the default file permissions for newly created files within the container. - - REDIS_URL=redis://localhost:6379/0 - - REDIS_BACKEND=redis://localhost:6379/0 + - REDIS_HOST=redis + - REDIS_PORT=6379 + - REDIS_DB=0 + - REDIS_URL=redis://redis:6379/0 + - REDIS_BACKEND=redis://redis:6379/0 + depends_on: + - redis + + redis: + image: redis:alpine + container_name: spotizerr-redis + restart: unless-stopped + volumes: + - redis-data:/data + command: redis-server --appendonly yes + +volumes: + redis-data: + driver: local diff --git a/entrypoint.sh b/entrypoint.sh index dbc8ef0..b380d4b 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -6,31 +6,8 @@ if [ -n "${UMASK}" ]; then umask "${UMASK}" fi -# Check if Redis should be started locally -if [[ -z "${REDIS_URL}" || "${REDIS_URL}" == *"localhost"* || "${REDIS_URL}" == *"127.0.0.1"* ]]; then - echo "Starting local Redis server..." - redis-server --daemonize yes - # Wait for Redis to be ready - until redis-cli ping &>/dev/null; do - echo "Waiting for Redis to start..." - sleep 1 - done - echo "Redis server is running." - - # If REDIS_URL is not set, set it to localhost - if [ -z "${REDIS_URL}" ]; then - export REDIS_URL="redis://localhost:6379/0" - echo "Set REDIS_URL to ${REDIS_URL}" - fi - - # If REDIS_BACKEND is not set, set it to the same as REDIS_URL - if [ -z "${REDIS_BACKEND}" ]; then - export REDIS_BACKEND="${REDIS_URL}" - echo "Set REDIS_BACKEND to ${REDIS_BACKEND}" - fi -else - echo "Using external Redis server at ${REDIS_URL}" -fi +# Redis is now in a separate container so we don't need to start it locally +echo "Using Redis at ${REDIS_URL}" # Check if both PUID and PGID are not set if [ -z "${PUID}" ] && [ -z "${PGID}" ]; then diff --git a/routes/utils/celery_config.py b/routes/utils/celery_config.py index b9bb4ad..0eaa53d 100644 --- a/routes/utils/celery_config.py +++ b/routes/utils/celery_config.py @@ -6,12 +6,15 @@ from pathlib import Path # Configure logging logger = logging.getLogger(__name__) -# Redis configuration -REDIS_HOST = os.getenv('REDIS_HOST', 'localhost') +# Redis configuration - read from environment variables +REDIS_HOST = os.getenv('REDIS_HOST', 'redis') REDIS_PORT = os.getenv('REDIS_PORT', '6379') REDIS_DB = os.getenv('REDIS_DB', '0') -REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}" -REDIS_BACKEND = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}" +REDIS_URL = os.getenv('REDIS_URL', f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}") +REDIS_BACKEND = os.getenv('REDIS_BACKEND', REDIS_URL) + +# Log Redis connection details +logger.info(f"Redis configuration: REDIS_URL={REDIS_URL}, REDIS_BACKEND={REDIS_BACKEND}") # Config path CONFIG_PATH = './config/main.json'