262 lines
9.2 KiB
Bash
262 lines
9.2 KiB
Bash
#!/bin/bash
|
||
set -e
|
||
|
||
# Ожидание готовности PostgreSQL
|
||
wait_for_postgres() {
|
||
echo "Waiting for PostgreSQL..."
|
||
python -c "
|
||
import psycopg2
|
||
import os
|
||
import sys
|
||
|
||
dbname = os.environ.get('DB_NAME', 'inventory_db')
|
||
user = os.environ.get('DB_USER', 'postgres')
|
||
password = os.environ.get('DB_PASSWORD', 'postgres')
|
||
host = os.environ.get('DB_HOST', 'db')
|
||
port = os.environ.get('DB_PORT', '5432')
|
||
|
||
print(f'Attempting connection to: host={host} port={port} dbname={dbname} user={user}')
|
||
|
||
try:
|
||
conn = psycopg2.connect(
|
||
dbname=dbname,
|
||
user=user,
|
||
password=password,
|
||
host=host,
|
||
port=port
|
||
)
|
||
conn.close()
|
||
print('Connection successful!')
|
||
exit(0)
|
||
except Exception as e:
|
||
print(f'Error connecting to PostgreSQL: {e}', file=sys.stderr)
|
||
exit(1)
|
||
"
|
||
while [ $? -ne 0 ]; do
|
||
echo "PostgreSQL is unavailable - sleeping"
|
||
sleep 2
|
||
python -c "
|
||
import psycopg2
|
||
import os
|
||
import sys
|
||
try:
|
||
conn = psycopg2.connect(
|
||
dbname=os.environ.get('DB_NAME', 'inventory_db'),
|
||
user=os.environ.get('DB_USER', 'postgres'),
|
||
password=os.environ.get('DB_PASSWORD', 'postgres'),
|
||
host=os.environ.get('DB_HOST', 'db'),
|
||
port=os.environ.get('DB_PORT', '5432')
|
||
)
|
||
conn.close()
|
||
exit(0)
|
||
except Exception as e:
|
||
print(f'Retry error: {e}', file=sys.stderr)
|
||
exit(1)
|
||
"
|
||
done
|
||
echo "PostgreSQL is up!"
|
||
}
|
||
|
||
# Ожидание готовности Redis
|
||
wait_for_redis() {
|
||
echo "Waiting for Redis..."
|
||
python -c "
|
||
import redis
|
||
import os
|
||
import sys
|
||
|
||
host = os.environ.get('REDIS_HOST', 'redis')
|
||
port = int(os.environ.get('REDIS_PORT', '6379'))
|
||
db = int(os.environ.get('REDIS_DB', '0'))
|
||
|
||
print(f'Attempting connection to Redis: host={host} port={port} db={db}')
|
||
|
||
try:
|
||
r = redis.Redis(host=host, port=port, db=db)
|
||
r.ping()
|
||
print('Redis connection successful!')
|
||
exit(0)
|
||
except Exception as e:
|
||
print(f'Error connecting to Redis: {e}', file=sys.stderr)
|
||
exit(1)
|
||
"
|
||
while [ $? -ne 0 ]; do
|
||
echo "Redis is unavailable - sleeping"
|
||
sleep 2
|
||
python -c "
|
||
import redis
|
||
import os
|
||
import sys
|
||
try:
|
||
r = redis.Redis(
|
||
host=os.environ.get('REDIS_HOST', 'redis'),
|
||
port=int(os.environ.get('REDIS_PORT', '6379')),
|
||
db=int(os.environ.get('REDIS_DB', '0'))
|
||
)
|
||
r.ping()
|
||
exit(0)
|
||
except Exception as e:
|
||
print(f'Redis retry error: {e}', file=sys.stderr)
|
||
exit(1)
|
||
"
|
||
done
|
||
echo "Redis is up!"
|
||
}
|
||
|
||
# Создание папок media и staticfiles с правильными правами
|
||
setup_directories() {
|
||
echo "Setting up media and static directories..."
|
||
|
||
# Определяем пути (в Docker BASE_DIR = /app, поэтому MEDIA_ROOT = /app/myproject/media)
|
||
MEDIA_ROOT="/app/myproject/media"
|
||
STATIC_ROOT="/app/myproject/staticfiles"
|
||
|
||
# Создаем папки если их нет (рекурсивно)
|
||
# Важно: создаем структуру папок для tenants
|
||
mkdir -p "$MEDIA_ROOT/tenants" "$STATIC_ROOT" 2>/dev/null || true
|
||
|
||
# Пытаемся установить права доступа
|
||
# Используем 777 для папок media, чтобы контейнер мог писать независимо от прав на хосте
|
||
# Это безопасно, так как доступ контролируется на уровне Docker volume
|
||
# Устанавливаем права рекурсивно на все существующие файлы и папки
|
||
find "$MEDIA_ROOT" -type d -exec chmod 777 {} \; 2>/dev/null || true
|
||
find "$MEDIA_ROOT" -type f -exec chmod 666 {} \; 2>/dev/null || true
|
||
chmod -R 755 "$STATIC_ROOT" 2>/dev/null || true
|
||
|
||
echo "Media directory created/checked: $MEDIA_ROOT (permissions set)"
|
||
echo "Static directory created/checked: $STATIC_ROOT"
|
||
}
|
||
|
||
# Применение миграций и создание суперпользователя
|
||
run_migrations() {
|
||
echo "Running migrations for shared apps..."
|
||
python manage.py migrate_schemas --shared
|
||
|
||
echo "Running migrations for tenant schemas..."
|
||
python manage.py migrate_schemas --tenant
|
||
|
||
echo "Collecting static files..."
|
||
python manage.py collectstatic --noinput
|
||
|
||
# Устанавливаем права ПОСЛЕ collectstatic
|
||
echo "Setting permissions on static files..."
|
||
STATIC_ROOT="/app/myproject/staticfiles"
|
||
find "$STATIC_ROOT" -type d -exec chmod 755 {} \; 2>/dev/null || true
|
||
find "$STATIC_ROOT" -type f -exec chmod 644 {} \; 2>/dev/null || true
|
||
|
||
echo "Ensuring public tenant exists..."
|
||
python /app/docker/create_public_tenant.py
|
||
}
|
||
|
||
# Создание PlatformAdmin если не существует
|
||
create_platform_admin() {
|
||
echo "Creating PlatformAdmin if not exists..."
|
||
python manage.py shell << EOF
|
||
from platform_admin.models import PlatformAdmin
|
||
import os
|
||
|
||
# Создаём PlatformAdmin из переменных окружения
|
||
email = os.environ.get('PLATFORM_ADMIN_EMAIL', 'admin@platform.com')
|
||
password = os.environ.get('PLATFORM_ADMIN_PASSWORD')
|
||
name = os.environ.get('PLATFORM_ADMIN_NAME', 'Platform Admin')
|
||
|
||
if not password:
|
||
print('WARNING: PLATFORM_ADMIN_PASSWORD not set. Skipping PlatformAdmin creation.')
|
||
print('Create PlatformAdmin manually via Django shell:')
|
||
print(' from platform_admin.models import PlatformAdmin')
|
||
print(' PlatformAdmin.objects.create_superuser(email="...", name="...", password="...")')
|
||
else:
|
||
if not PlatformAdmin.objects.filter(email=email).exists():
|
||
admin = PlatformAdmin.objects.create_superuser(
|
||
email=email,
|
||
name=name,
|
||
password=password
|
||
)
|
||
print(f'PlatformAdmin {email} created successfully!')
|
||
else:
|
||
print(f'PlatformAdmin {email} already exists.')
|
||
EOF
|
||
}
|
||
|
||
# Если manage.py не в текущей директории, но есть в подпапке myproject
|
||
if [ ! -f "manage.py" ] && [ -d "myproject" ]; then
|
||
# Пытаемся войти в директорию, перенаправляя ошибки в /dev/null
|
||
if cd myproject 2>/dev/null; then
|
||
echo "Changing directory to myproject..."
|
||
# Устанавливаем PYTHONPATH чтобы Python мог найти модуль myproject
|
||
export PYTHONPATH=$(pwd):$PYTHONPATH
|
||
echo "PYTHONPATH set to: $PYTHONPATH"
|
||
else
|
||
# Если не можем войти в директорию (проблема с правами), устанавливаем PYTHONPATH из текущей директории
|
||
echo "Warning: Cannot access myproject directory (permission denied). Setting PYTHONPATH to include myproject..."
|
||
export PYTHONPATH=/app/myproject:$PYTHONPATH
|
||
echo "PYTHONPATH set to: $PYTHONPATH"
|
||
fi
|
||
fi
|
||
|
||
case "$1" in
|
||
web)
|
||
wait_for_postgres
|
||
wait_for_redis
|
||
setup_directories
|
||
run_migrations
|
||
create_platform_admin
|
||
echo "Starting Gunicorn..."
|
||
exec gosu appuser gunicorn myproject.wsgi:application \
|
||
--bind 0.0.0.0:8000 \
|
||
--workers 3 \
|
||
--threads 2 \
|
||
--timeout 600 \
|
||
--access-logfile - \
|
||
--error-logfile - \
|
||
--capture-output
|
||
;;
|
||
celery-worker)
|
||
wait_for_postgres
|
||
wait_for_redis
|
||
setup_directories
|
||
echo "Starting Celery Worker for photo processing and product import..."
|
||
exec gosu appuser celery -A myproject worker \
|
||
-l info \
|
||
--concurrency=4
|
||
;;
|
||
celery-beat)
|
||
wait_for_postgres
|
||
wait_for_redis
|
||
echo "Starting Celery Beat..."
|
||
exec gosu appuser celery -A myproject beat -l info
|
||
;;
|
||
migrate)
|
||
wait_for_postgres
|
||
# Миграции тоже запускаем от gosu
|
||
gosu appuser python manage.py migrate_schemas --shared
|
||
gosu appuser python manage.py migrate_schemas --tenant
|
||
gosu appuser python manage.py collectstatic --noinput
|
||
|
||
# Права уже выставлены setup_directories (который запускается перед этим в case web/celery,
|
||
# но для migrate мы можем вызвать его явно или просто поправить права на статику)
|
||
# В данном блоке setup_directories не вызывался в оригинальном скрипте, но лучше вызвать если хотим гарантий
|
||
# setup_directories
|
||
|
||
# Для migrate обычно важно просто создать схемы.
|
||
create_platform_admin
|
||
;;
|
||
collectstatic)
|
||
wait_for_postgres
|
||
setup_directories
|
||
echo "Collecting static files..."
|
||
gosu appuser python manage.py collectstatic --noinput
|
||
echo "Setting permissions on static files..."
|
||
STATIC_ROOT="/app/myproject/staticfiles"
|
||
find "$STATIC_ROOT" -type d -exec chmod 755 {} \; 2>/dev/null || true
|
||
find "$STATIC_ROOT" -type f -exec chmod 644 {} \; 2>/dev/null || true
|
||
echo "Static files collected and permissions set."
|
||
;;
|
||
shell)
|
||
exec gosu appuser python manage.py shell
|
||
;;
|
||
*)
|
||
exec "$@"
|
||
;;
|
||
esac
|