304 lines
9.1 KiB
Bash
Executable File
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"
|