ai-review/vector/build-base.sh
2025-06-15 13:52:26 +00:00

283 lines
8.7 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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)"