#!/bin/bash # ============================================================================== # WACE PLM Docker 실행 스크립트 (Linux용) # ============================================================================== set -e # 오류 발생 시 스크립트 종료 # 색상 코드 정의 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 로그 함수 log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${BLUE}[STEP]${NC} $1" } # 도움말 함수 show_help() { cat << EOF WACE PLM Docker 실행 스크립트 (Linux용) 사용법: $0 [OPTION] 옵션: -e, --env ENV 환경 설정 (dev|prod|standalone) [기본값: dev] -c, --clean Docker 시스템 정리 실행 -r, --restart 컨테이너 재시작 (중지 후 시작) -s, --stop 컨테이너 중지 -l, --logs 컨테이너 로그 확인 -i, --init-db 데이터베이스 초기화 (dbexport.pgsql 임포트) -h, --help 도움말 출력 예시: $0 # 개발환경 실행 $0 -e dev # 개발환경 실행 $0 -e prod # 운영환경 실행 $0 -e standalone # 로컬 DB 포함 독립실행환경 $0 -e dev -c # 개발환경 실행 (Docker 정리 포함) $0 -i # 데이터베이스 초기화 $0 -s # 컨테이너 중지 $0 -l # 로그 확인 EOF } # 시스템 체크 check_system() { log_step "시스템 환경 체크 중..." # OS 확인 if [[ "$(uname -s)" != "Linux" ]]; then log_error "이 스크립트는 Linux 환경에서만 실행됩니다." log_error "현재 OS: $(uname -s)" exit 1 fi # Docker 설치 확인 if ! command -v docker &> /dev/null; then log_error "Docker가 설치되지 않았습니다." log_error "Docker 설치 후 다시 시도하세요." exit 1 fi # Docker Compose 설치 확인 if ! command -v docker-compose &> /dev/null; then log_error "Docker Compose가 설치되지 않았습니다." log_error "Docker Compose 설치 후 다시 시도하세요." exit 1 fi # Docker 서비스 상태 확인 (WSL2 + Docker Desktop 환경) if ! docker info &> /dev/null; then log_warn "Docker 서비스가 실행되지 않았습니다." log_warn "Windows에서 Docker Desktop을 시작해주세요." exit 1 fi log_info "시스템 환경 체크 완료" } # 환경 변수 로드 load_env_vars() { local env_file=".env.$1" if [ -f "$env_file" ]; then log_info "환경 변수 로드 중: $env_file" set -a source "$env_file" set +a export NODE_ENV="$1" else log_error "환경 변수 파일을 찾을 수 없습니다: $env_file" exit 1 fi } # Docker 시스템 정리 clean_docker() { log_step "Docker 시스템 정리 중..." # 사용하지 않는 컨테이너, 이미지, 볼륨 정리 docker system prune -af docker image prune -af docker volume prune -af log_info "Docker 시스템 정리 완료" } # 컨테이너 중지 stop_containers() { log_step "컨테이너 중지 중..." if [ "$ENVIRONMENT" = "prod" ]; then docker-compose -f docker-compose.prod.yml down elif [ "$ENVIRONMENT" = "standalone" ]; then docker-compose -f docker-compose.standalone.yml down else docker-compose -f docker-compose.dev.yml down fi log_info "컨테이너 중지 완료" } # 컨테이너 시작 start_containers() { local compose_file if [ "$ENVIRONMENT" = "prod" ]; then compose_file="docker-compose.prod.yml" log_step "운영환경 컨테이너 시작 중..." # 운영환경의 경우 Git 업데이트 if [ -d ".git" ]; then log_info "Git 리포지토리 업데이트 중..." git reset --hard git checkout main if ! git fetch origin; then log_error "Git fetch 실패" exit 1 fi if ! git reset --hard origin/main; then log_error "Git reset 실패" exit 1 fi log_info "Git 업데이트 완료" fi elif [ "$ENVIRONMENT" = "standalone" ]; then compose_file="docker-compose.standalone.yml" log_step "독립실행환경 컨테이너 시작 중..." log_info "로컬 PostgreSQL 데이터베이스가 포함됩니다." else compose_file="docker-compose.dev.yml" log_step "개발환경 컨테이너 시작 중..." fi # 컨테이너 빌드 및 시작 docker-compose -f "$compose_file" up --build --force-recreate -d log_info "컨테이너 시작 완료" } # 컨테이너 상태 확인 check_status() { log_step "컨테이너 상태 확인 중..." if [ "$ENVIRONMENT" = "prod" ]; then docker-compose -f docker-compose.prod.yml ps elif [ "$ENVIRONMENT" = "standalone" ]; then docker-compose -f docker-compose.standalone.yml ps else docker-compose -f docker-compose.dev.yml ps fi } # 로그 확인 show_logs() { log_step "컨테이너 로그 확인 중..." if [ "$ENVIRONMENT" = "prod" ]; then docker-compose -f docker-compose.prod.yml logs -f elif [ "$ENVIRONMENT" = "standalone" ]; then docker-compose -f docker-compose.standalone.yml logs -f else docker-compose -f docker-compose.dev.yml logs -f fi } # 데이터베이스 초기화 init_database() { log_step "데이터베이스 초기화 시작..." # dbexport.pgsql 파일 존재 확인 if [ ! -f "db/dbexport.pgsql" ]; then log_error "db/dbexport.pgsql 파일을 찾을 수 없습니다." exit 1 fi log_info "파일 크기: $(du -h db/dbexport.pgsql | cut -f1)" # 환경에 따른 데이터베이스 연결 정보 설정 if [ "$ENVIRONMENT" = "standalone" ]; then # standalone 환경은 로컬 DB 컨테이너 사용 log_info "standalone 환경: 로컬 PostgreSQL 컨테이너가 자동으로 초기화됩니다." return 0 else # 외부 DB 사용 환경 if [ -f ".env.development" ] && [ "$ENVIRONMENT" = "dev" ]; then source .env.development elif [ -f ".env.production" ] && [ "$ENVIRONMENT" = "prod" ]; then source .env.production fi # 환경 변수에서 DB 정보 추출 DB_HOST=$(echo $DB_URL | sed -n 's/.*\/\/.*@\([^:]*\):.*/\1/p') DB_PORT=$(echo $DB_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p') DB_NAME=$(echo $DB_URL | sed -n 's/.*\/\([^?]*\).*/\1/p') if [ -z "$DB_HOST" ] || [ -z "$DB_PORT" ] || [ -z "$DB_NAME" ]; then log_error "데이터베이스 연결 정보를 추출할 수 없습니다." log_error "DB_URL: $DB_URL" exit 1 fi log_info "데이터베이스 연결 정보:" log_info " 호스트: $DB_HOST" log_info " 포트: $DB_PORT" log_info " 데이터베이스: $DB_NAME" log_info " 사용자: $DB_USERNAME" # Docker를 사용하여 데이터베이스 초기화 실행 log_info "Docker를 사용하여 데이터베이스 초기화 중..." # 연결 테스트 if ! docker run --rm postgres:16-alpine psql "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" -c "SELECT 1;" > /dev/null 2>&1; then log_error "데이터베이스 연결에 실패했습니다." log_error "연결 정보를 확인해주세요." exit 1 fi log_info "데이터베이스 연결 성공!" # 기존 데이터 확인 EXISTING_TABLES=$(docker run --rm postgres:16-alpine psql "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" | tr -d ' ') if [ "$EXISTING_TABLES" -gt 0 ]; then log_warn "기존 데이터가 발견되었습니다. (테이블 수: $EXISTING_TABLES)" log_warn "계속하면 기존 데이터가 덮어쓰여집니다." # 운영환경에서는 추가 확인 if [ "$ENVIRONMENT" = "prod" ]; then log_warn "운영환경에서 데이터베이스를 초기화하려고 합니다!" log_warn "정말 계속하시겠습니까? 기존 데이터가 모두 삭제됩니다." log_warn "계속하려면 'YES'를 입력하세요:" read -r confirmation if [ "$confirmation" != "YES" ]; then log_info "데이터베이스 초기화가 취소되었습니다." exit 0 fi fi else log_info "빈 데이터베이스입니다. 초기화를 진행합니다." fi # 백업 생성 BACKUP_FILE="backup_$(date +%Y%m%d_%H%M%S).sql" log_info "기존 데이터 백업 생성 중: $BACKUP_FILE" docker run --rm -v "$(pwd):/workspace" postgres:16-alpine pg_dump "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" > $BACKUP_FILE 2>/dev/null || log_warn "백업 생성 실패 (기존 데이터가 없을 수 있습니다)" # 역할 생성 log_info "데이터베이스 역할 생성 중..." docker run --rm postgres:16-alpine psql "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" -c "CREATE ROLE IF NOT EXISTS pro_search; CREATE ROLE IF NOT EXISTS search_user;" || log_warn "역할 생성 실패 (이미 존재할 수 있습니다)" # 데이터베이스 임포트 log_info "데이터베이스 임포트 시작... (시간이 오래 걸릴 수 있습니다)" docker run --rm -v "$(pwd)/db:/db" postgres:16-alpine psql "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" -v ON_ERROR_STOP=1 -f /db/dbexport.pgsql if [ $? -eq 0 ]; then log_info "데이터베이스 임포트 완료!" else log_error "데이터베이스 임포트 실패!" log_error "백업 파일을 사용하여 복원할 수 있습니다: $BACKUP_FILE" exit 1 fi # 임포트 검증 log_info "임포트 검증 중..." TABLE_COUNT=$(docker run --rm postgres:16-alpine psql "postgresql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" | tr -d ' ') log_info "생성된 테이블 수: $TABLE_COUNT" if [ "$TABLE_COUNT" -gt 0 ]; then log_info "데이터베이스 초기화가 성공적으로 완료되었습니다!" if [ -f "$BACKUP_FILE" ]; then log_info "백업 파일: $BACKUP_FILE" fi else log_warn "데이터베이스 초기화에 문제가 있을 수 있습니다." log_warn "테이블이 생성되지 않았습니다." fi fi log_info "데이터베이스 초기화 완료" } # 메인 실행 함수 main() { local ENVIRONMENT="dev" local CLEAN_DOCKER=false local RESTART=false local STOP_ONLY=false local SHOW_LOGS=false local INIT_DB=false # 인자 파싱 while [[ $# -gt 0 ]]; do case $1 in -e|--env) ENVIRONMENT="$2" shift 2 ;; -c|--clean) CLEAN_DOCKER=true shift ;; -r|--restart) RESTART=true shift ;; -s|--stop) STOP_ONLY=true shift ;; -l|--logs) SHOW_LOGS=true shift ;; -i|--init-db) INIT_DB=true shift ;; -h|--help) show_help exit 0 ;; *) log_error "알 수 없는 옵션: $1" show_help exit 1 ;; esac done # 환경 검증 if [[ "$ENVIRONMENT" != "dev" && "$ENVIRONMENT" != "prod" && "$ENVIRONMENT" != "standalone" ]]; then log_error "유효하지 않은 환경: $ENVIRONMENT (dev, prod, standalone만 허용)" exit 1 fi log_info "WACE PLM Docker 실행 스크립트 시작" log_info "환경: $ENVIRONMENT" # 시스템 체크 check_system # 환경 변수 로드 if [ "$ENVIRONMENT" = "prod" ]; then load_env_vars "production" elif [ "$ENVIRONMENT" = "standalone" ]; then # standalone 환경은 별도 환경 변수 파일이 없으므로 기본값 사용 log_info "standalone 환경: 내장 설정 사용" else load_env_vars "development" fi # 데이터베이스 초기화만 하는 경우 if [ "$INIT_DB" = true ]; then init_database exit 0 fi # 로그만 확인하는 경우 if [ "$SHOW_LOGS" = true ]; then show_logs exit 0 fi # 컨테이너 중지만 하는 경우 if [ "$STOP_ONLY" = true ]; then stop_containers exit 0 fi # 재시작 또는 일반 시작 if [ "$RESTART" = true ]; then stop_containers fi # Docker 정리 if [ "$CLEAN_DOCKER" = true ]; then clean_docker fi # 컨테이너 시작 start_containers # 상태 확인 check_status log_info "WACE PLM Docker 실행 완료!" log_info "애플리케이션 접속:" if [ "$ENVIRONMENT" = "prod" ]; then log_info " - https://waceplm.esgrin.com" log_info " - https://autoclave.co.kr" elif [ "$ENVIRONMENT" = "standalone" ]; then log_info " - http://localhost:8090" log_info " - 데이터베이스: localhost:5432 (postgres/waceplm0909!!)" else log_info " - http://localhost:8090" fi log_info "로그 확인: $0 -l" log_info "컨테이너 중지: $0 -s" log_info "데이터베이스 초기화: $0 -i" } # 스크립트 실행 main "$@"