feat: NAS(Synology) 배포 도구 및 마이그레이션 추가
- deploy/ 폴더: docker-compose.synology.yml, deploy.sh, package.sh - NAS 배포 패키지 생성/전송/설치 자동화 스크립트 - 삭제 로그 테이블 마이그레이션 (018_add_deletion_log_table.sql) - 사진 필드 마이그레이션 유틸리티 (migrate_add_photo_fields.py) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
106
deploy/deploy.sh
Executable file
106
deploy/deploy.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# M-Project Synology NAS 배포 스크립트
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo "M-Project (부적합관리) 배포 시작"
|
||||
echo "=========================================="
|
||||
|
||||
# 1. 환경 변수 파일 확인
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ .env 파일이 없습니다."
|
||||
echo " .env.synology 파일을 복사하고 값을 수정하세요:"
|
||||
echo " cp .env.synology .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 비밀번호 미설정 확인
|
||||
if grep -q "변경필수" .env; then
|
||||
echo "❌ .env 파일에 기본값이 남아있습니다."
|
||||
echo " 모든 '변경필수' 항목을 실제 값으로 수정하세요."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Docker 이미지 빌드
|
||||
echo ""
|
||||
echo "🔨 Docker 이미지 빌드 중..."
|
||||
docker-compose -f docker-compose.synology.yml build --no-cache
|
||||
|
||||
# 3. 기존 컨테이너 중지
|
||||
echo ""
|
||||
echo "🛑 기존 컨테이너 중지 중..."
|
||||
docker-compose -f docker-compose.synology.yml down 2>/dev/null || true
|
||||
|
||||
# 4. 컨테이너 시작
|
||||
echo ""
|
||||
echo "🚀 컨테이너 시작 중..."
|
||||
docker-compose -f docker-compose.synology.yml up -d
|
||||
|
||||
# 5. DB 초기화 대기
|
||||
echo ""
|
||||
echo "⏳ 데이터베이스 초기화 대기 중 (15초)..."
|
||||
sleep 15
|
||||
|
||||
# 6. DB 마이그레이션 실행
|
||||
echo ""
|
||||
echo "📦 DB 마이그레이션 실행 중..."
|
||||
for sql_file in ./init-db/*.sql; do
|
||||
if [ -f "$sql_file" ]; then
|
||||
echo " 실행: $(basename "$sql_file")"
|
||||
docker exec -i m-project-db psql -U "${POSTGRES_USER:-mproject}" "${POSTGRES_DB:-mproject}" < "$sql_file" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# 7. 데이터베이스 복원 (백업 파일이 있는 경우)
|
||||
BACKUP_FILE=$(ls -t backup_*.sql 2>/dev/null | head -1)
|
||||
if [ -n "$BACKUP_FILE" ]; then
|
||||
echo ""
|
||||
read -p "📦 DB 백업 발견: $BACKUP_FILE - 복원하시겠습니까? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "📦 데이터베이스 복원 중..."
|
||||
docker exec -i m-project-db psql -U "${POSTGRES_USER:-mproject}" "${POSTGRES_DB:-mproject}" < "$BACKUP_FILE"
|
||||
echo "✅ 데이터베이스 복원 완료"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 8. 상태 확인
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "📊 컨테이너 상태"
|
||||
echo "=========================================="
|
||||
docker-compose -f docker-compose.synology.yml ps
|
||||
|
||||
# 9. 헬스체크
|
||||
echo ""
|
||||
echo "🔍 서비스 확인 중..."
|
||||
sleep 5
|
||||
|
||||
check_service() {
|
||||
local name="$1"
|
||||
local url="$2"
|
||||
printf " %-20s " "$name"
|
||||
status=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "$url" 2>/dev/null || echo "000")
|
||||
if [ "$status" -ge 200 ] && [ "$status" -lt 400 ]; then
|
||||
echo "✅ OK ($status)"
|
||||
else
|
||||
echo "❌ FAIL ($status)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_service "Backend API" "http://localhost:16000/api/health"
|
||||
check_service "Frontend" "http://localhost:16080/"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "✅ 배포 완료!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "접속 URL:"
|
||||
echo " - 웹 UI: http://NAS_IP:16080"
|
||||
echo " - API: http://NAS_IP:16000"
|
||||
echo " - DB: NAS_IP:16432 (PostgreSQL)"
|
||||
echo ""
|
||||
80
deploy/docker-compose.synology.yml
Normal file
80
deploy/docker-compose.synology.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# PostgreSQL 데이터베이스
|
||||
db:
|
||||
image: postgres:15-alpine
|
||||
container_name: m-project-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-mproject}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-mproject}
|
||||
TZ: Asia/Seoul
|
||||
PGTZ: Asia/Seoul
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./init-db:/docker-entrypoint-initdb.d
|
||||
ports:
|
||||
- "16432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mproject}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- m-project-network
|
||||
|
||||
# FastAPI 백엔드
|
||||
backend:
|
||||
build: ./backend
|
||||
container_name: m-project-backend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-mproject}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-mproject}
|
||||
SECRET_KEY: ${SECRET_KEY}
|
||||
ALGORITHM: HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: 10080
|
||||
ADMIN_USERNAME: ${ADMIN_USERNAME:-hyungi}
|
||||
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
|
||||
TZ: Asia/Seoul
|
||||
volumes:
|
||||
- uploads:/app/uploads
|
||||
ports:
|
||||
- "16000:8000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- m-project-network
|
||||
|
||||
# Nginx 프론트엔드
|
||||
nginx:
|
||||
build: ./nginx
|
||||
container_name: m-project-nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "16080:80"
|
||||
volumes:
|
||||
- ./frontend:/usr/share/nginx/html:ro
|
||||
- uploads:/app/uploads
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- m-project-network
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
driver: local
|
||||
uploads:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
m-project-network:
|
||||
driver: bridge
|
||||
name: m-project-network
|
||||
83
deploy/package.sh
Executable file
83
deploy/package.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# M-Project 배포 패키지 생성 스크립트
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
DEPLOY_DIR="$SCRIPT_DIR"
|
||||
PACKAGE_DIR="$DEPLOY_DIR/mproject-package"
|
||||
|
||||
echo "=========================================="
|
||||
echo "M-Project 배포 패키지 생성"
|
||||
echo "=========================================="
|
||||
|
||||
# 기존 패키지 삭제
|
||||
rm -rf "$PACKAGE_DIR"
|
||||
mkdir -p "$PACKAGE_DIR"
|
||||
|
||||
# 1. Docker 설정 파일
|
||||
echo "📦 Docker 설정 복사..."
|
||||
cp "$DEPLOY_DIR/docker-compose.synology.yml" "$PACKAGE_DIR/docker-compose.yml"
|
||||
cp "$DEPLOY_DIR/.env.synology" "$PACKAGE_DIR/.env.example"
|
||||
cp "$DEPLOY_DIR/deploy.sh" "$PACKAGE_DIR/"
|
||||
chmod +x "$PACKAGE_DIR/deploy.sh"
|
||||
|
||||
# 2. 데이터베이스 백업 생성
|
||||
echo "📦 DB 백업 시도..."
|
||||
if docker exec m-project-db pg_dump -U mproject mproject > "$PACKAGE_DIR/backup_$(date +%Y%m%d_%H%M%S).sql" 2>/dev/null; then
|
||||
echo " ✅ DB 백업 완료"
|
||||
else
|
||||
echo " ⚠️ DB 백업 건너뜀 (컨테이너 미실행)"
|
||||
rm -f "$PACKAGE_DIR"/backup_*.sql
|
||||
fi
|
||||
|
||||
# 3. 소스 코드 복사
|
||||
echo "📦 소스 코드 복사..."
|
||||
|
||||
# Backend
|
||||
mkdir -p "$PACKAGE_DIR/backend"
|
||||
rsync -a --exclude='__pycache__' --exclude='.git' --exclude='venv' --exclude='*.pyc' \
|
||||
"$PROJECT_DIR/backend/" "$PACKAGE_DIR/backend/"
|
||||
|
||||
# Frontend
|
||||
mkdir -p "$PACKAGE_DIR/frontend"
|
||||
rsync -a --exclude='.git' --exclude='uploads' \
|
||||
"$PROJECT_DIR/frontend/" "$PACKAGE_DIR/frontend/"
|
||||
|
||||
# Nginx
|
||||
mkdir -p "$PACKAGE_DIR/nginx"
|
||||
rsync -a "$PROJECT_DIR/nginx/" "$PACKAGE_DIR/nginx/"
|
||||
|
||||
# 4. init-db 폴더 (마이그레이션 스크립트)
|
||||
mkdir -p "$PACKAGE_DIR/init-db"
|
||||
if [ -d "$PROJECT_DIR/backend/migrations" ]; then
|
||||
cp "$PROJECT_DIR/backend/migrations"/*.sql "$PACKAGE_DIR/init-db/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 5. 압축
|
||||
echo "📦 압축 중..."
|
||||
cd "$DEPLOY_DIR"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
tar -czf "mproject-deploy-$TIMESTAMP.tar.gz" -C "$DEPLOY_DIR" mproject-package
|
||||
|
||||
# 크기 확인
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "✅ 패키지 생성 완료!"
|
||||
echo "=========================================="
|
||||
ls -lh "$DEPLOY_DIR/mproject-deploy-$TIMESTAMP.tar.gz"
|
||||
echo ""
|
||||
echo "파일: $DEPLOY_DIR/mproject-deploy-$TIMESTAMP.tar.gz"
|
||||
echo ""
|
||||
echo "Synology NAS로 전송:"
|
||||
echo " scp $DEPLOY_DIR/mproject-deploy-$TIMESTAMP.tar.gz admin@NAS_IP:/volume1/docker/"
|
||||
echo ""
|
||||
echo "NAS에서 설치:"
|
||||
echo " cd /volume1/docker/"
|
||||
echo " tar -xzf mproject-deploy-$TIMESTAMP.tar.gz"
|
||||
echo " cd mproject-package"
|
||||
echo " cp .env.example .env && vi .env"
|
||||
echo " bash deploy.sh"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user