Spaces:
Paused
Paused
File size: 4,314 Bytes
769e684 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
IMAGE_FILE="${PROJECT_DIR}/govon-image.tar.gz"
ENV_TEMPLATE="${PROJECT_DIR}/.env.airgap.example"
ENV_FILE="${PROJECT_DIR}/.env"
API_KEY_PLACEHOLDER="CHANGE_ME_TO_SECURE_RANDOM_KEY"
BM25_INDEX_HMAC_KEY_PLACEHOLDER="CHANGE_ME_TO_SECURE_HMAC_KEY"
extract_env_value() {
local key="$1"
local file="$2"
awk -F= -v key="$key" '
$0 ~ "^[[:space:]]*" key "=" {
sub(/^[^=]*=/, "", $0)
print $0
exit
}
' "$file"
}
require_secure_env_value() {
local key="$1"
local placeholder="$2"
local value
value="$(extract_env_value "$key" "$ENV_FILE")"
if [ -z "$value" ] || [ "$value" = "$placeholder" ]; then
echo "[ERROR] ${key} κ°μ΄ λΉμ΄ μκ±°λ μμ placeholder κ·Έλλ‘μ
λλ€."
echo " ${ENV_FILE}μμ ${key}λ₯Ό μμ ν μμ λ¬Έμμ΄λ‘ μμ ν λ€ λ€μ μ€ννμΈμ."
exit 1
fi
}
echo "=== GovOn μ€νλΌμΈ λ°°ν¬ μ€ν¬λ¦½νΈ ==="
# 1. Docker μ€μΉ νμΈ
if ! command -v docker &>/dev/null; then
echo "[ERROR] Dockerκ° μ€μΉλμ΄ μμ§ μμ΅λλ€."
echo "μ€μΉ κ°μ΄λ: https://docs.docker.com/engine/install/"
exit 1
fi
echo "[OK] Docker: $(docker --version)"
# 2. Docker Compose νμΈ
if ! docker compose version &>/dev/null; then
echo "[ERROR] Docker Composeκ° μ€μΉλμ΄ μμ§ μμ΅λλ€."
exit 1
fi
echo "[OK] Docker Compose: $(docker compose version --short)"
# 3. NVIDIA Container Toolkit νμΈ (κ²½κ³ λ§)
if docker info 2>/dev/null | grep -q "Runtimes.*nvidia"; then
echo "[OK] NVIDIA Container Toolkit κ°μ§λ¨"
else
echo "[WARNING] NVIDIA Container Toolkitμ΄ κ°μ§λμ§ μμμ΅λλ€."
echo "GPU κ°μμ΄ νμν©λλ€: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html"
fi
# 4. μ΄λ―Έμ§ νμΌ νμΈ λ° λ‘λ
if [ ! -f "$IMAGE_FILE" ]; then
echo "[ERROR] μ΄λ―Έμ§ νμΌμ μ°Ύμ μ μμ΅λλ€: $IMAGE_FILE"
exit 1
fi
echo "Docker μ΄λ―Έμ§ λ‘λ μ€... (μκ°μ΄ μμλ μ μμ΅λλ€)"
gunzip -c "$IMAGE_FILE" | docker load
echo "[OK] μ΄λ―Έμ§ λ‘λ μλ£"
# 5. νκ²½λ³μ ν
νλ¦Ώ μ€λΉ
if [ ! -f "$ENV_FILE" ] && [ -f "$ENV_TEMPLATE" ]; then
cp "$ENV_TEMPLATE" "$ENV_FILE"
echo "[OK] .env νμΌμ .env.airgap.example κΈ°μ€μΌλ‘ μμ±νμ΅λλ€."
echo " API_KEY, BM25_INDEX_HMAC_KEY, CORS_ORIGINS λ±μ μμ ν λ€ μ¬μ€ννμΈμ."
fi
if [ -z "${MODEL_PATH:-}" ] && [ ! -f "$ENV_FILE" ]; then
echo "[INFO] MODEL_PATHκ° μ€μ λμ§ μμμ΅λλ€."
echo " μ€νλΌμΈ νκ²½μμλ 컨ν
μ΄λ λ΄λΆ κ²½λ‘λ₯Ό μ§μ νμΈμ:"
echo " export MODEL_PATH=/app/models/EXAONE-4.0-32B-AWQ"
fi
if [ ! -f "$ENV_FILE" ]; then
echo "[ERROR] νκ²½λ³μ νμΌμ μ°Ύμ μ μμ΅λλ€: $ENV_FILE"
exit 1
fi
require_secure_env_value "API_KEY" "$API_KEY_PLACEHOLDER"
require_secure_env_value "BM25_INDEX_HMAC_KEY" "$BM25_INDEX_HMAC_KEY_PLACEHOLDER"
# 6. λ³Όλ₯¨ λλ ν 리 μμ±
echo "λ³Όλ₯¨ λλ ν 리 μμ± μ€..."
mkdir -p \
"${PROJECT_DIR}/models" \
"${PROJECT_DIR}/data" \
"${PROJECT_DIR}/agents" \
"${PROJECT_DIR}/configs" \
"${PROJECT_DIR}/logs" \
"${PROJECT_DIR}/.cache"
echo "[OK] λ³Όλ₯¨ λλ ν 리 μ€λΉ μλ£"
# 7. 컨ν
μ΄λ μ€ν
echo "컨ν
μ΄λ μμ μ€..."
docker compose --env-file "${ENV_FILE}" -f "${PROJECT_DIR}/docker-compose.offline.yml" up -d
echo "[OK] 컨ν
μ΄λ μμλ¨"
# 8. ν¬μ€μ²΄ν¬ λκΈ°
echo "μλ² μμ λκΈ° μ€... (μ΅λ 120μ΄)"
for i in $(seq 1 24); do
if curl -sf http://localhost:8000/health > /dev/null 2>&1; then
echo ""
echo "=============================="
echo "[SUCCESS] GovOn μλ²κ° μ μ μμλμμ΅λλ€!"
echo "API μ£Όμ: http://localhost:8000"
echo "ν¬μ€μ²΄ν¬: http://localhost:8000/health"
echo "=============================="
exit 0
fi
printf "."
sleep 5
done
echo ""
echo "[ERROR] μλ² μμ μ€ν¨ (120μ΄ νμμμ)"
echo "λ‘κ·Έ νμΈ: docker compose --env-file ${ENV_FILE} -f ${PROJECT_DIR}/docker-compose.offline.yml logs"
exit 1
|