Files
document-server/scripts/update-synology.sh

304 lines
9.1 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# Document Server - Synology 업데이트 스크립트
# Git을 통한 무중단 업데이트 및 롤백 지원
# =============================================================================
set -e
# 색상 정의
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 로그 함수
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 환경 설정
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
COMPOSE_FILE="docker-compose.synology.yml"
BACKUP_DIR="/volume2/document-storage/backups"
UPDATE_LOG="/volume1/docker/document-server/logs/update.log"
# 업데이트 모드 설정
UPDATE_MODE="${1:-safe}" # safe, force, rollback
log_info "🔄 Document Server 업데이트 시작 (모드: $UPDATE_MODE)"
echo "$(date '+%Y-%m-%d %H:%M:%S') - 업데이트 시작: $UPDATE_MODE" >> "$UPDATE_LOG"
cd "$PROJECT_DIR"
# 현재 상태 확인
log_info "📊 현재 상태 확인 중..."
# Git 상태 확인
if [ ! -d ".git" ]; then
log_error "Git 저장소가 아닙니다. Git 클론으로 설치해주세요."
exit 1
fi
# 현재 커밋 해시 저장 (롤백용)
CURRENT_COMMIT=$(git rev-parse HEAD)
CURRENT_BRANCH=$(git branch --show-current)
echo "이전 커밋: $CURRENT_COMMIT" >> "$UPDATE_LOG"
log_info "현재 브랜치: $CURRENT_BRANCH"
log_info "현재 커밋: ${CURRENT_COMMIT:0:8}"
# 컨테이너 상태 확인
if docker-compose -f "$COMPOSE_FILE" ps -q | grep -q .; then
CONTAINERS_RUNNING=true
log_info "컨테이너가 실행 중입니다"
else
CONTAINERS_RUNNING=false
log_warning "컨테이너가 실행 중이지 않습니다"
fi
# 롤백 모드
if [ "$UPDATE_MODE" = "rollback" ]; then
log_warning "🔙 롤백 모드 실행"
# 마지막 성공한 커밋으로 롤백
LAST_SUCCESS=$(tail -n 20 "$UPDATE_LOG" | grep "업데이트 성공" | tail -n 1 | awk '{print $6}')
if [ -z "$LAST_SUCCESS" ]; then
log_error "롤백할 커밋을 찾을 수 없습니다"
exit 1
fi
log_info "롤백 대상 커밋: $LAST_SUCCESS"
# 롤백 실행
git reset --hard "$LAST_SUCCESS"
# 컨테이너 재시작
if [ "$CONTAINERS_RUNNING" = true ]; then
log_info "컨테이너 재시작 중..."
docker-compose -f "$COMPOSE_FILE" down
docker-compose -f "$COMPOSE_FILE" up -d --build
fi
log_success "롤백 완료: $LAST_SUCCESS"
echo "$(date '+%Y-%m-%d %H:%M:%S') - 롤백 완료: $LAST_SUCCESS" >> "$UPDATE_LOG"
exit 0
fi
# 업데이트 가능 여부 확인
log_info "🔍 업데이트 확인 중..."
# 원격 저장소에서 최신 정보 가져오기
git fetch origin
# 업데이트 가능한 커밋 수 확인
COMMITS_BEHIND=$(git rev-list --count HEAD..origin/$CURRENT_BRANCH)
if [ "$COMMITS_BEHIND" -eq 0 ]; then
log_success "이미 최신 버전입니다"
exit 0
fi
log_info "업데이트 가능한 커밋: $COMMITS_BEHIND개"
# 변경사항 미리보기
log_info "📝 변경사항 미리보기:"
git log --oneline HEAD..origin/$CURRENT_BRANCH | head -10
# Safe 모드에서 사용자 확인
if [ "$UPDATE_MODE" = "safe" ]; then
echo ""
read -p "업데이트를 진행하시겠습니까? (y/N): " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "업데이트가 취소되었습니다"
exit 0
fi
fi
# 백업 생성
log_info "💾 백업 생성 중..."
BACKUP_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="pre_update_${BACKUP_TIMESTAMP}"
# 데이터베이스 백업
if [ "$CONTAINERS_RUNNING" = true ]; then
docker-compose -f "$COMPOSE_FILE" exec -T database pg_dump -U docuser document_db > "$BACKUP_DIR/db_${BACKUP_NAME}.sql"
log_success "데이터베이스 백업 완료"
fi
# 설정 파일 백업
tar -czf "$BACKUP_DIR/config_${BACKUP_NAME}.tar.gz" \
/volume1/docker/document-server/config/ \
.env.synology 2>/dev/null || true
log_success "설정 파일 백업 완료"
# Git 업데이트 실행
log_info "📥 코드 업데이트 중..."
# 로컬 변경사항 임시 저장 (있는 경우)
if ! git diff --quiet; then
log_warning "로컬 변경사항을 임시 저장합니다"
git stash push -m "Auto-stash before update $BACKUP_TIMESTAMP"
fi
# 업데이트 실행
git pull origin "$CURRENT_BRANCH"
NEW_COMMIT=$(git rev-parse HEAD)
log_success "코드 업데이트 완료: ${NEW_COMMIT:0:8}"
# Docker 이미지 업데이트 확인
log_info "🐳 Docker 이미지 업데이트 확인 중..."
# Dockerfile이나 requirements.txt 변경 확인
NEED_REBUILD=false
if git diff --name-only "$CURRENT_COMMIT" "$NEW_COMMIT" | grep -E "(Dockerfile|requirements.txt|pyproject.toml|package.json)" > /dev/null; then
NEED_REBUILD=true
log_info "의존성 변경 감지 - 이미지 재빌드 필요"
fi
# 컨테이너 업데이트
if [ "$CONTAINERS_RUNNING" = true ]; then
log_info "🔄 서비스 업데이트 중..."
if [ "$NEED_REBUILD" = true ]; then
log_info "이미지 재빌드 중..."
# 무중단 업데이트를 위한 단계별 재시작
docker-compose -f "$COMPOSE_FILE" build --no-cache backend
docker-compose -f "$COMPOSE_FILE" up -d --no-deps backend
# 헬스체크 대기
log_info "백엔드 헬스체크 대기 중..."
sleep 30
# Nginx 업데이트 (필요시)
if git diff --name-only "$CURRENT_COMMIT" "$NEW_COMMIT" | grep -E "(nginx|frontend)" > /dev/null; then
docker-compose -f "$COMPOSE_FILE" build --no-cache nginx
docker-compose -f "$COMPOSE_FILE" up -d --no-deps nginx
fi
else
log_info "설정 파일만 업데이트 - 재시작 중..."
docker-compose -f "$COMPOSE_FILE" restart backend nginx
fi
# 서비스 상태 확인
sleep 10
# 헬스체크
HEALTH_CHECK_FAILED=false
# 백엔드 헬스체크
if ! curl -f http://localhost:24102/health > /dev/null 2>&1; then
log_error "백엔드 헬스체크 실패"
HEALTH_CHECK_FAILED=true
fi
# 프론트엔드 헬스체크
if ! curl -f http://localhost:24100/ > /dev/null 2>&1; then
log_error "프론트엔드 헬스체크 실패"
HEALTH_CHECK_FAILED=true
fi
# 헬스체크 실패 시 롤백
if [ "$HEALTH_CHECK_FAILED" = true ]; then
log_error "헬스체크 실패 - 자동 롤백 실행"
# 이전 커밋으로 롤백
git reset --hard "$CURRENT_COMMIT"
# 컨테이너 롤백
docker-compose -f "$COMPOSE_FILE" down
docker-compose -f "$COMPOSE_FILE" up -d --build
log_error "업데이트 실패 - 이전 버전으로 롤백됨"
echo "$(date '+%Y-%m-%d %H:%M:%S') - 업데이트 실패 (롤백): $NEW_COMMIT -> $CURRENT_COMMIT" >> "$UPDATE_LOG"
exit 1
fi
log_success "서비스 업데이트 완료"
else
log_info "컨테이너가 실행 중이지 않아 서비스 업데이트를 건너뜁니다"
fi
# 데이터베이스 마이그레이션 확인
log_info "🗄️ 데이터베이스 마이그레이션 확인 중..."
if git diff --name-only "$CURRENT_COMMIT" "$NEW_COMMIT" | grep -E "(migrations|models)" > /dev/null; then
log_warning "데이터베이스 스키마 변경 감지"
if [ "$CONTAINERS_RUNNING" = true ]; then
log_info "마이그레이션 실행 중..."
docker-compose -f "$COMPOSE_FILE" exec -T backend python -m alembic upgrade head || true
log_success "마이그레이션 완료"
else
log_warning "컨테이너가 실행 중이지 않아 마이그레이션을 건너뜁니다"
fi
fi
# 업데이트 완료
log_success "🎉 업데이트 완료!"
echo ""
echo "=== 업데이트 정보 ==="
echo "이전 커밋: ${CURRENT_COMMIT:0:8}"
echo "새 커밋: ${NEW_COMMIT:0:8}"
echo "업데이트된 커밋 수: $COMMITS_BEHIND"
echo "백업 위치: $BACKUP_DIR/*_${BACKUP_NAME}.*"
echo ""
# 변경사항 요약
echo "=== 주요 변경사항 ==="
git log --oneline "$CURRENT_COMMIT".."$NEW_COMMIT" | head -5
echo ""
echo "=== 서비스 상태 ==="
if [ "$CONTAINERS_RUNNING" = true ]; then
docker-compose -f "$COMPOSE_FILE" ps
echo ""
echo "🌐 웹 인터페이스: http://localhost:24100"
echo "🔧 API 문서: http://localhost:24102/docs"
fi
# 성공 로그 기록
echo "$(date '+%Y-%m-%d %H:%M:%S') - 업데이트 성공: $CURRENT_COMMIT -> $NEW_COMMIT" >> "$UPDATE_LOG"
# 정리 작업
log_info "🧹 정리 작업 중..."
# 오래된 백업 파일 정리 (30일 이상)
find "$BACKUP_DIR" -name "pre_update_*" -mtime +30 -delete 2>/dev/null || true
# Docker 이미지 정리
docker system prune -f > /dev/null 2>&1 || true
log_success "업데이트 프로세스 완료"
# 모니터링 실행 제안
echo ""
echo "💡 업데이트 후 시스템 상태를 확인하려면:"
echo " ./scripts/monitor-synology.sh"
echo ""
echo "🔙 문제가 있으면 롤백하려면:"
echo " ./scripts/update-synology.sh rollback"