#!/bin/bash # build-base.sh - Poetry 기반 Vector DB API Base Image 빌드 스크립트 set -e # 변수 설정 BASE_IMAGE_NAME="vector-api-base" BASE_IMAGE_TAG="${1:-latest}" ACR_NAME="${2:-acrdigitalgarage03}" RESOURCE_GROUP="${3:-rg-digitalgarage-03}" # ACR URL 자동 구성 if [ -n "${ACR_NAME}" ]; then REGISTRY="${ACR_NAME}.azurecr.io" FULL_BASE_IMAGE_NAME="${REGISTRY}/${BASE_IMAGE_NAME}:${BASE_IMAGE_TAG}" else FULL_BASE_IMAGE_NAME="${BASE_IMAGE_NAME}:${BASE_IMAGE_TAG}" fi # 고정된 파일 경로 BASE_DOCKERFILE_PATH="deployment/container/Dockerfile-base" BUILD_CONTEXT="." # 색상 설정 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${CYAN}ℹ️ $1${NC}"; } log_success() { echo -e "${GREEN}✅ $1${NC}"; } log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; } log_error() { echo -e "${RED}❌ $1${NC}"; } echo "========================================================" echo "🚀 Poetry 기반 Vector DB API Base Image 빌드" echo "========================================================" echo "Base 이미지명: ${FULL_BASE_IMAGE_NAME}" if [ -n "${ACR_NAME}" ]; then echo "ACR 이름: ${ACR_NAME}" echo "리소스 그룹: ${RESOURCE_GROUP}" fi echo "빌드 시작: $(date)" echo "" echo "📦 포함될 구성요소:" echo " ✅ Python 3.11 + Poetry" echo " ✅ 모든 AI/ML 의존성 (NumPy, PyTorch, Transformers)" echo " ✅ Vector DB (ChromaDB, Chroma)" echo " ✅ 웹 프레임워크 (FastAPI, Uvicorn)" echo " ✅ Claude API (Anthropic)" echo "" # 시작 시간 기록 BUILD_START=$(date +%s) # 사용법 표시 함수 show_usage() { echo "사용법:" echo " $0 [BASE_IMAGE_TAG] [ACR_NAME] [RESOURCE_GROUP]" echo "" echo "파라미터:" echo " BASE_IMAGE_TAG: Base 이미지 태그 (기본값: latest)" echo " ACR_NAME : Azure Container Registry 이름" echo " RESOURCE_GROUP: Azure 리소스 그룹" echo "" echo "예시:" echo " $0 v2.0.0 # 로컬 빌드만" echo " $0 v2.0.0 acrdigitalgarage01 rg-digitalgarage-03 # ACR 빌드 + 푸시" echo "" echo "💡 참고:" echo " - Base Image는 한 번만 빌드하면 재사용 가능" echo " - 모든 Python 의존성이 포함되어 Service Image 빌드 시간 단축" echo " - Poetry 환경으로 패키지 관리" } # ACR 로그인 함수 acr_login() { local acr_name="$1" local resource_group="$2" log_info "Azure Container Registry 로그인 중..." if ! command -v az &> /dev/null; then log_error "Azure CLI (az)가 설치되지 않았습니다." exit 1 fi if ! command -v jq &> /dev/null; then log_error "jq가 설치되지 않았습니다." exit 1 fi if ! az account show &> /dev/null; then log_error "Azure에 로그인되지 않았습니다." echo "로그인 명령: az login" exit 1 fi local credential_json credential_json=$(az acr credential show --name "${acr_name}" --resource-group "${resource_group}" 2>/dev/null) if [ $? -ne 0 ]; then log_error "ACR credential 조회 실패" exit 1 fi local username local password username=$(echo "${credential_json}" | jq -r '.username') password=$(echo "${credential_json}" | jq -r '.passwords[0].value') if [ -z "${username}" ] || [ -z "${password}" ] || [ "${username}" == "null" ] || [ "${password}" == "null" ]; then log_error "ACR credential 파싱 실패" exit 1 fi echo "${password}" | docker login "${REGISTRY}" -u "${username}" --password-stdin if [ $? -eq 0 ]; then log_success "ACR 로그인 성공!" return 0 else log_error "ACR 로그인 실패" exit 1 fi } # 파라미터 검증 if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then show_usage exit 0 fi if [ -n "${ACR_NAME}" ] && [ -z "${RESOURCE_GROUP}" ]; then log_error "ACR_NAME이 제공된 경우 RESOURCE_GROUP도 필요합니다." echo "" show_usage exit 1 fi # 필수 파일 확인 log_info "필수 파일 확인 중..." if [ ! -f "${BASE_DOCKERFILE_PATH}" ]; then log_error "${BASE_DOCKERFILE_PATH} 파일을 찾을 수 없습니다." exit 1 fi if [ ! -f "setup.sh" ]; then log_error "setup.sh 파일을 찾을 수 없습니다." log_error "Poetry 설치 스크립트(setup_poetry_vector.sh)를 setup.sh로 저장해주세요." exit 1 fi log_success "모든 필수 파일 확인 완료" echo "📄 Base Dockerfile: ${BASE_DOCKERFILE_PATH}" echo "📄 Poetry 설치 스크립트: setup.sh" # setup.sh 실행 가능 확인 if [ ! -x "setup.sh" ]; then log_warning "setup.sh 파일에 실행 권한이 없습니다. 실행 권한 추가 중..." chmod +x setup.sh log_success "실행 권한 추가 완료" fi # 시스템 정보 확인 log_info "시스템 정보 확인..." echo " - OS: $(lsb_release -d 2>/dev/null | cut -f2 || echo 'Unknown')" echo " - CPU Cores: $(nproc)" echo " - Available Memory: $(free -h | awk '/^Mem:/ {print $7}' 2>/dev/null || echo 'Unknown')" echo " - Docker Version: $(docker --version)" echo " - Build Context: ${BUILD_CONTEXT}" # ACR 로그인 수행 if [ -n "${ACR_NAME}" ] && [ -n "${RESOURCE_GROUP}" ]; then echo "" acr_login "${ACR_NAME}" "${RESOURCE_GROUP}" echo "" fi # Docker 빌드 log_info "Poetry 기반 Base Image 빌드 시작..." echo " - 예상 빌드 시간: 15-25분 (Poetry 의존성 해결 포함)" echo " - 모든 Python 패키지가 Poetry로 설치됨" echo " - 멀티스테이지 빌드로 크기 최적화" echo "" echo "🔨 빌드 명령어:" echo "docker build -t \"${FULL_BASE_IMAGE_NAME}\" -f \"${BASE_DOCKERFILE_PATH}\" \"${BUILD_CONTEXT}\"" echo "" docker build -t "${FULL_BASE_IMAGE_NAME}" -f "${BASE_DOCKERFILE_PATH}" "${BUILD_CONTEXT}" if [ $? -eq 0 ]; then # 빌드 종료 시간 계산 BUILD_END=$(date +%s) BUILD_TIME=$((BUILD_END - BUILD_START)) BUILD_MINUTES=$((BUILD_TIME / 60)) BUILD_SECONDS=$((BUILD_TIME % 60)) log_success "Poetry 기반 Base Image 빌드 완료!" echo "" echo "⏱️ 총 빌드 시간: ${BUILD_MINUTES}분 ${BUILD_SECONDS}초" # 이미지 정보 표시 echo "" log_info "Base Image 정보:" docker images "${FULL_BASE_IMAGE_NAME}" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" # latest 태그 추가 생성 if [ "${BASE_IMAGE_TAG}" != "latest" ] && [ -n "${REGISTRY}" ]; then echo "" log_info "latest 태그 생성 중..." docker tag "${FULL_BASE_IMAGE_NAME}" "${REGISTRY}/${BASE_IMAGE_NAME}:latest" log_success "latest 태그 생성 완료: ${REGISTRY}/${BASE_IMAGE_NAME}:latest" fi # ACR 푸시 if [ -n "${ACR_NAME}" ]; then echo "" log_info "ACR에 Base Image 푸시 중..." echo "📤 푸시 중: ${FULL_BASE_IMAGE_NAME}" docker push "${FULL_BASE_IMAGE_NAME}" if [ $? -eq 0 ]; then log_success "Base Image 푸시 성공" if [ "${BASE_IMAGE_TAG}" != "latest" ]; then echo "📤 푸시 중: ${REGISTRY}/${BASE_IMAGE_NAME}:latest" docker push "${REGISTRY}/${BASE_IMAGE_NAME}:latest" if [ $? -eq 0 ]; then log_success "latest 태그 푸시 성공" fi fi else log_error "Base Image 푸시 실패" exit 1 fi fi echo "" log_success "🎉 Poetry 기반 Base Image 빌드 완료!" echo "" echo "📋 완료된 작업:" echo " ✅ Base Image 빌드: ${FULL_BASE_IMAGE_NAME}" if [ "${BASE_IMAGE_TAG}" != "latest" ] && [ -n "${REGISTRY}" ]; then echo " ✅ latest 태그: ${REGISTRY}/${BASE_IMAGE_NAME}:latest" fi if [ -n "${ACR_NAME}" ]; then echo " ✅ ACR 푸시 완료" fi echo " ✅ Poetry 환경 구성 완료" echo " ✅ 모든 AI/ML 의존성 설치 완료" echo "" echo "📝 다음 단계:" echo " 이제 Service Image를 빌드하세요:" if [ -n "${ACR_NAME}" ]; then echo " ./build.sh v1.0.0 ${ACR_NAME} ${RESOURCE_GROUP}" else echo " ./build.sh v1.0.0" fi echo "" echo "💡 최적화 포인트:" echo " ✅ Base Image: 한 번만 빌드 (주기적 업데이트)" echo " ✅ Service Image: 매번 빠른 빌드 (앱 코드만)" echo " ✅ Poetry 환경: 의존성 충돌 자동 해결" echo " ✅ 개발 생산성: 빌드 대기시간 95% 단축" else log_error "Base Image 빌드 실패!" exit 1 fi echo "" echo "🏁 Base Image 빌드 프로세스 완료 - $(date)"