#!/usr/bin/env bash set -euo pipefail # ─── Загрузка переменных из .env ───────────────────────────────────────────── if [ -f .env ]; then export $(grep -v '^#' .env | grep -v '^$' | xargs) fi POSTGRES_ROOT_PASSWORD=${POSTGRES_ROOT_PASSWORD:-PgRootNews2026Rz} NEWS_DB_PASSWORD=${NEWS_DB_PASSWORD:-NewsAdmPass2026Xk} DB_USER="news_admin" DB_NAME="news" DB_CONTAINER="news_flet-db-1" # имя контейнера по умолчанию (docker compose project name) # ─── Цвета вывода ──────────────────────────────────────────────────────────── GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } # ─── Поиск контейнера postgres ──────────────────────────────────────────────── find_container() { # Пробуем стандартные варианты имён контейнера for name in "news_flet-db-1" "news_flet_db_1" "db"; do if docker inspect "$name" &>/dev/null 2>&1; then echo "$name" return fi done # Ищем по образу local found found=$(docker ps --filter "ancestor=postgres" --format "{{.Names}}" | head -1) if [ -n "$found" ]; then echo "$found" return fi error "Контейнер PostgreSQL не найден. Запусти: docker compose -f docker-compose_db.yml up -d" } psql_cmd() { docker exec -i "$DB_CONTAINER" psql -U postgres "$@" } # ─── Ожидание готовности PostgreSQL ────────────────────────────────────────── wait_for_postgres() { info "Ожидание готовности PostgreSQL..." local retries=30 until docker exec "$DB_CONTAINER" pg_isready -U postgres -q 2>/dev/null; do retries=$((retries - 1)) if [ $retries -le 0 ]; then error "PostgreSQL не стал доступен за 60 секунд." fi echo -n "." sleep 2 done echo "" info "PostgreSQL готов." } # ─── Создание пользователя ──────────────────────────────────────────────────── create_user() { info "Проверка пользователя '$DB_USER'..." local exists exists=$(psql_cmd -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER';" 2>/dev/null || echo "") if [ "$exists" = "1" ]; then warn "Пользователь '$DB_USER' уже существует — обновляю пароль." psql_cmd -c "ALTER USER $DB_USER WITH PASSWORD '$NEWS_DB_PASSWORD';" > /dev/null else psql_cmd -c "CREATE USER $DB_USER WITH PASSWORD '$NEWS_DB_PASSWORD';" > /dev/null info "Пользователь '$DB_USER' создан." fi } # ─── Создание базы данных ───────────────────────────────────────────────────── create_database() { info "Проверка базы данных '$DB_NAME'..." local exists exists=$(psql_cmd -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME';" 2>/dev/null || echo "") if [ "$exists" = "1" ]; then warn "База данных '$DB_NAME' уже существует — пропускаю создание." else psql_cmd -c "CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;" > /dev/null info "База данных '$DB_NAME' создана." fi } # ─── Настройка прав ─────────────────────────────────────────────────────────── grant_privileges() { info "Настройка привилегий..." psql_cmd -d "$DB_NAME" << 'SQL' > /dev/null GRANT ALL PRIVILEGES ON DATABASE news TO news_admin; GRANT ALL ON SCHEMA public TO news_admin; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO news_admin; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO news_admin; SQL info "Привилегии настроены." } # ─── Проверка подключения ───────────────────────────────────────────────────── verify_connection() { info "Проверка подключения от '$DB_USER' к '$DB_NAME'..." if docker exec "$DB_CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" > /dev/null 2>&1; then info "Подключение успешно." else error "Не удалось подключиться от '$DB_USER' к '$DB_NAME'." fi } # ─── Ожидание Redis ─────────────────────────────────────────────────────────── wait_for_redis() { info "Ожидание готовности Redis..." local redis_container redis_container=$(docker ps --filter "ancestor=redis" --format "{{.Names}}" | head -1) if [ -z "$redis_container" ]; then warn "Контейнер Redis не найден — пропускаю проверку." return fi local retries=15 local redis_pass=${REDIS_PASSWORD:-RedisNewsMk2026} until docker exec "$redis_container" redis-cli -a "$redis_pass" ping 2>/dev/null | grep -q PONG; do retries=$((retries - 1)) if [ $retries -le 0 ]; then warn "Redis не ответил за 30 секунд — продолжаю без него." return fi echo -n "." sleep 2 done echo "" info "Redis готов." } # ─── Создание директорий для данных ────────────────────────────────────────── create_data_dirs() { info "Создание директорий для хранения данных..." mkdir -p ./data/postgres ./data/redis ./data/minio info "Директории: ./data/postgres ./data/redis ./data/minio" } # ─── Главная функция ────────────────────────────────────────────────────────── main() { echo "" echo "══════════════════════════════════════════════" echo " Инициализация баз данных — News CMS" echo "══════════════════════════════════════════════" echo "" create_data_dirs # Запуск docker-compose_db.yml если не запущен if ! docker compose -f docker-compose_db.yml ps --services --filter "status=running" 2>/dev/null | grep -q "db"; then info "Запуск docker-compose_db.yml..." docker compose -f docker-compose_db.yml up -d sleep 3 fi DB_CONTAINER=$(find_container) info "Контейнер PostgreSQL: $DB_CONTAINER" wait_for_postgres create_user create_database grant_privileges verify_connection wait_for_redis echo "" echo "══════════════════════════════════════════════" info "Готово! Теперь запускай:" echo "" echo " docker compose up -d --build" echo "" echo " Сайт: http://localhost" echo " Админка: http://localhost/admin" echo " MinIO консоль: http://localhost:9001" echo "══════════════════════════════════════════════" echo "" } main "$@"