implement gunicorn WSGI

This commit is contained in:
Bryan Van Deusen
2025-08-14 13:34:29 -04:00
parent 3420cf01ff
commit 0d56daa664
4 changed files with 52 additions and 44 deletions
+3
View File
@@ -4,6 +4,7 @@ from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from werkzeug.middleware.proxy_fix import ProxyFix
db = SQLAlchemy()
@@ -22,6 +23,8 @@ def create_app(config_class='config.Config'):
login_manager.init_app(app)
login_manager.login_view = 'auth.login'
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
from app.main import main
from app.auth import auth
+8 -16
View File
@@ -1,31 +1,23 @@
# Dockerfile
FROM python:slim
# Set work directory
WORKDIR /app
# Install PostgreSQL client
# Only what you actually need (ffmpeg kept for video/thumbs)
RUN apt-get update && \
apt-get install -y postgresql-client ffmpeg && \
apt-get clean && \
apt-get install -y --no-install-recommends ffmpeg && \
rm -rf /var/lib/apt/lists/*
# Copy project files
# Install deps first for better layer caching
COPY requirements.txt .
RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt
# Copy the rest of the app
COPY . .
# Install dependencies
RUN pip install --upgrade pip && pip install -r requirements.txt
# Copy and prepare entrypoint script
# Entrypoint controls migrations, background worker, and Gunicorn
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Set environment variables
ENV FLASK_APP=run.py
ENV FLASK_RUN_HOST=0.0.0.0
# Expose port
EXPOSE 5000
# Use entrypoint script
ENTRYPOINT ["/entrypoint.sh"]
+39 -27
View File
@@ -1,36 +1,48 @@
#!/bin/bash
#!/usr/bin/env sh
set -e
# Default to sqlite if not specified
DB_TYPE="${DB_TYPE:-sqlite}"
# Ensure Flask CLI finds your app
export FLASK_APP=run.py
export FLASK_ENV=production
# Wait for PostgreSQL if needed
if [ "$DB_TYPE" = "postgresql" ]; then
MAX_WAIT=180
WAIT_INTERVAL=2
WAITED=0
echo "Database type is PostgreSQL. Waiting for database to be ready..."
until pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" > /dev/null 2>&1; do
if [ $WAITED -ge $MAX_WAIT ]; then
echo "Timeout: Could not connect to the database at $DB_HOST:$DB_PORT within $MAX_WAIT seconds."
# --- Migrations with simple retry (no pg_isready needed) ---
if [ "${RUN_DB_MIGRATIONS:-1}" = "1" ]; then
ATTEMPTS="${MIGRATION_MAX_ATTEMPTS:-30}" # ~90s default with 3s sleep
SLEEP_SECS="${MIGRATION_RETRY_SLEEP:-3}"
i=1
echo "Applying migrations (up to $ATTEMPTS attempts)..."
until flask db upgrade; do
if [ "$i" -ge "$ATTEMPTS" ]; then
echo "ERROR: Migrations failed after $ATTEMPTS attempts."
exit 1
fi
echo "Waiting for database at $DB_HOST:$DB_PORT... ($WAITED/$MAX_WAIT seconds)"
sleep $WAIT_INTERVAL
WAITED=$((WAITED + WAIT_INTERVAL))
echo "DB not ready yet; retrying in ${SLEEP_SECS}s ($i/$ATTEMPTS)…"
sleep "$SLEEP_SECS"
i=$((i+1))
done
echo "Database is ready."
else
echo "Database type is SQLite. Skipping PostgreSQL readiness check."
fi
# Apply migrations
echo "Applying database migrations..."
flask db upgrade
# --- Start the image import worker exactly once per container ---
if [ "${RUN_IMAGE_IMPORTER:-1}" = "1" ]; then
echo "Starting image import worker (background)…"
python image_import_worker.py &
fi
# Start periodic image import in background
echo "import worker waiting for flag"
python image_import_worker.py &
# --- Start Gunicorn ---
GUNICORN_BIND="${GUNICORN_BIND:-0.0.0.0:5000}"
GUNICORN_WORKERS="${GUNICORN_WORKERS:-2}"
GUNICORN_THREADS="${GUNICORN_THREADS:-4}"
GUNICORN_TIMEOUT="${GUNICORN_TIMEOUT:-120}"
GUNICORN_OPTS="${GUNICORN_OPTS:-}"
# Start the Flask app
echo "Starting Flask app..."
exec flask run --host=0.0.0.0 --port=5000
echo "Starting Gunicorn on ${GUNICORN_BIND}"
exec gunicorn \
--bind "${GUNICORN_BIND}" \
--workers "${GUNICORN_WORKERS}" \
--worker-class gthread \
--threads "${GUNICORN_THREADS}" \
--timeout "${GUNICORN_TIMEOUT}" \
--access-logfile - \
--error-logfile - \
${GUNICORN_OPTS} \
run:app
+2 -1
View File
@@ -7,4 +7,5 @@ psycopg2-binary
email-validator
pillow
exifread
imagehash
imagehash
gunicorn