#!/usr/bin/env bash # # Odtworzenie instancji z kopii zapasowej. # # ./scripts/restore.sh ./backups/20260828-143000 # # UWAGA: skrypt NADPISUJE biezaca baze i pliki MinIO. Wymaga potwierdzenia. # Przed odtworzeniem warto zrobic kopie stanu biezacego: # ./scripts/backup.sh set -euo pipefail COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}" ENV_FILE="${ENV_FILE:-.env.production}" SOURCE="${1:-}" compose() { docker compose -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" "$@" } log() { echo "[$(date +%H:%M:%S)] $*" } if [ -z "${SOURCE}" ]; then echo "Uzycie: $0 " >&2 echo "Dostepne kopie:" >&2 ls -1 ./backups 2>/dev/null | sed 's/^/ /' >&2 || echo " brak katalogu ./backups" >&2 exit 1 fi if [ ! -f "${SOURCE}/baza.dump" ]; then echo "BLAD: brak ${SOURCE}/baza.dump" >&2 exit 1 fi if [ -f "${SOURCE}/INFO.txt" ]; then echo "--- Kopia do odtworzenia ---" cat "${SOURCE}/INFO.txt" echo "----------------------------" fi DB_NAME="$(grep -E '^DB_NAME=' "${ENV_FILE}" | cut -d= -f2-)" DB_USER="$(grep -E '^DB_USER=' "${ENV_FILE}" | cut -d= -f2-)" echo echo "UWAGA: ta operacja skasuje biezaca zawartosc bazy ${DB_NAME} i plikow MinIO." read -r -p "Wpisz ODTWORZ, aby kontynuowac: " CONFIRM if [ "${CONFIRM}" != "ODTWORZ" ]; then echo "Przerwano." exit 1 fi # Backend musi byc zatrzymany, inaczej trzyma polaczenia do bazy # i pisze do niej w trakcie odtwarzania. log "Zatrzymuje backend..." compose stop backend log "Odtwarzam baze..." # --clean --if-exists usuwa istniejace obiekty przed wgraniem compose exec -T postgres pg_restore \ -U "${DB_USER}" \ -d "${DB_NAME}" \ --clean \ --if-exists \ --no-owner \ < "${SOURCE}/baza.dump" log "Baza odtworzona" if [ -f "${SOURCE}/minio.tar.gz" ]; then log "Odtwarzam pliki MinIO..." # Obraz MinIO nie zawiera tar, wiec rozpakowujemy z pomocniczego kontenera # podpietego do tego samego wolumenu. MinIO musi byc w tym czasie zatrzymane, # zeby nie pisalo do katalogu w trakcie podmiany. MINIO_CONTAINER="$(compose ps -q minio)" if [ -z "${MINIO_CONTAINER}" ]; then echo "BLAD: kontener minio nie istnieje" >&2 exit 1 fi MINIO_VOLUME="$(docker inspect "${MINIO_CONTAINER}" \ --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}')" if [ -z "${MINIO_VOLUME}" ]; then echo "BLAD: nie udalo sie ustalic wolumenu MinIO" >&2 exit 1 fi log " wolumen: ${MINIO_VOLUME}" compose stop minio # czyscimy katalog danych, zeby nie zostaly pliki spoza kopii docker run --rm -v "${MINIO_VOLUME}:/data" alpine:3.20 \ sh -c 'rm -rf /data/..?* /data/.[!.]* /data/* 2>/dev/null || true' docker run --rm -i -v "${MINIO_VOLUME}:/data" alpine:3.20 \ tar xzf - -C /data < "${SOURCE}/minio.tar.gz" log "Pliki MinIO odtworzone" compose start minio else log "Pominieto MinIO: brak minio.tar.gz w kopii" fi log "Uruchamiam backend..." compose start backend log "Czekam na gotowosc aplikacji..." for i in $(seq 1 60); do if compose exec -T backend sh -c 'wget -qO- http://localhost:8080/api/health >/dev/null 2>&1'; then log "Aplikacja odpowiada" break fi sleep 2 done echo log "Gotowe. Sprawdz recznie:" echo " curl http://localhost:\${FRONTEND_PORT_EXPOSED:-8081}/api/health" echo " zaloguj sie do panelu i sprawdz liste webinarow"