dify / docker /entrypoint.sh
Severian's picture
Setup Dify for HF Spaces deployment with optimized Docker configuration
e26861f
#!/bin/bash
set -e
echo "Starting Dify services..."
# Database connection check based on type
if [ "${DATABASE_TYPE}" = "sqlite" ]; then
echo "Using SQLite database at ${SQLITE_PATH}"
mkdir -p $(dirname "${SQLITE_PATH}")
touch "${SQLITE_PATH}"
else
check_postgres() {
local max_attempts=30
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Checking PostgreSQL connection to ${DB_HOST}:${DB_PORT} (attempt $attempt/$max_attempts)..."
if pg_isready -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USERNAME}" -d "${DB_DATABASE}"; then
return 0
fi
attempt=$((attempt + 1))
sleep 5
done
return 1
}
if ! check_postgres; then
echo "Failed to connect to PostgreSQL, falling back to SQLite..."
export DATABASE_TYPE="sqlite"
mkdir -p $(dirname "${SQLITE_PATH}")
touch "${SQLITE_PATH}"
fi
fi
# Redis connection check function with HF Spaces compatibility
check_redis() {
local max_attempts=30
local attempt=1
# Ensure Redis is installed
if ! command -v redis-server >/dev/null 2>&1; then
echo "Redis server not found, installing..."
apt-get update && apt-get install -y redis-server
fi
# For HF Spaces, start local Redis by default
if [ "${REDIS_TYPE}" = "local" ] || [ "${SPACE_ID}" != "" ]; then
echo "Starting local Redis server..."
mkdir -p /data/redis
redis-server --daemonize yes --dir /data/redis --port 6379 --requirepass "${REDIS_PASSWORD:-difyai123456}"
export REDIS_HOST=localhost
sleep 2
if redis-cli -h localhost -p 6379 -a "${REDIS_PASSWORD:-difyai123456}" ping > /dev/null 2>&1; then
echo "Local Redis server started successfully"
return 0
fi
fi
while [ $attempt -le $max_attempts ]; do
if redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" -a "${REDIS_PASSWORD}" ping > /dev/null 2>&1; then
echo "Redis is ready!"
return 0
fi
echo "Redis is unavailable (attempt $attempt/$max_attempts) - retrying..."
attempt=$((attempt + 1))
sleep 5
if [ $attempt -eq $max_attempts ]; then
echo "Falling back to local Redis..."
export REDIS_TYPE="local"
export REDIS_HOST=localhost
mkdir -p /data/redis
redis-server --daemonize yes --dir /data/redis --port 6379 --requirepass "${REDIS_PASSWORD:-difyai123456}"
sleep 2
if redis-cli -h localhost -p 6379 -a "${REDIS_PASSWORD:-difyai123456}" ping > /dev/null 2>&1; then
echo "Local Redis server started successfully"
return 0
fi
fi
done
return 1
}
# Try to connect to Redis
check_redis || {
echo "Failed to connect to Redis after all attempts"
exit 1
}
# Install Python dependencies if not in pre-built image
if [ "${INSTALL_DEPENDENCIES}" = "true" ]; then
cd /app/api
echo "Installing Python dependencies..."
if [ -f "requirements.txt" ]; then
pip install --no-cache-dir -r requirements.txt
elif [ -f "../requirements.txt" ]; then
pip install --no-cache-dir -r ../requirements.txt
else
echo "Using pre-installed dependencies from Docker image"
fi
else
echo "Using pre-installed dependencies from Docker image"
fi
# Ensure we're in the correct directory for database operations
cd /app/api
# Initialize database if needed
if [ ! -f ".db_initialized" ]; then
echo "Running database migrations..."
FLASK_APP=app.py flask db upgrade
if [ $? -eq 0 ]; then
touch .db_initialized
echo "Database initialization completed successfully"
else
echo "Database initialization failed"
exit 1
fi
fi
# Start services
echo "Starting API server on port 7860..."
gunicorn --bind 0.0.0.0:7860 \
--workers 1 \
--worker-class gevent \
--timeout 200 \
--preload \
app:app &
# Start Next.js web server
cd /app/web
echo "Starting Next.js server on port 3000..."
# Ensure standalone directory exists
if [ ! -d ".next/standalone" ]; then
echo "Error: Next.js standalone build not found"
exit 1
fi
# Copy static files if they exist
if [ -d ".next/static" ]; then
mkdir -p .next/standalone/.next
cp -r .next/static .next/standalone/.next/
fi
# Copy public files if they exist
if [ -d "public" ]; then
cp -r public .next/standalone/
fi
cd .next/standalone
echo "Starting Next.js standalone server..."
NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
node server.js &
# Wait for both processes
wait
# Add to entrypoint.sh
export MALLOC_ARENA_MAX=2
export NODE_OPTIONS="--max-old-space-size=2048"