lily_fast_api / scripts /test_docker_deployment.py
gbrabbit's picture
Fresh start for HF Spaces deployment
526927a
#!/usr/bin/env python3
"""
Docker ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์Šคํฌ๋ฆฝํŠธ
Docker ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ
"""
import requests
import time
import subprocess
import json
import sys
import os
def check_docker_installation():
"""Docker ์„ค์น˜ ํ™•์ธ"""
try:
result = subprocess.run(['docker', '--version'],
capture_output=True, text=True, check=True)
print(f"โœ… Docker ์„ค์น˜๋จ: {result.stdout.strip()}")
return True
except subprocess.CalledProcessError:
print("โŒ Docker๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return False
except FileNotFoundError:
print("โŒ Docker๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return False
def check_docker_compose_installation():
"""Docker Compose ์„ค์น˜ ํ™•์ธ"""
try:
result = subprocess.run(['docker-compose', '--version'],
capture_output=True, text=True, check=True)
print(f"โœ… Docker Compose ์„ค์น˜๋จ: {result.stdout.strip()}")
return True
except subprocess.CalledProcessError:
print("โŒ Docker Compose๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return False
except FileNotFoundError:
print("โŒ Docker Compose๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return False
def check_dockerfile():
"""Dockerfile ์กด์žฌ ํ™•์ธ"""
if os.path.exists('Dockerfile'):
print("โœ… Dockerfile ์กด์žฌ")
return True
else:
print("โŒ Dockerfile์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
return False
def check_docker_compose_file():
"""docker-compose.yml ์กด์žฌ ํ™•์ธ"""
if os.path.exists('docker-compose.yml'):
print("โœ… docker-compose.yml ์กด์žฌ")
return True
else:
print("โŒ docker-compose.yml์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
return False
def build_docker_image():
"""Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ"""
try:
print("๐Ÿ”จ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์ค‘...")
result = subprocess.run(['docker-compose', 'build'],
capture_output=True, text=True, check=True)
print("โœ… Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์„ฑ๊ณต")
return True
except subprocess.CalledProcessError as e:
print(f"โŒ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์‹คํŒจ: {e.stderr}")
return False
def start_services():
"""์„œ๋น„์Šค ์‹œ์ž‘"""
try:
print("๐Ÿš€ ์„œ๋น„์Šค ์‹œ์ž‘ ์ค‘...")
result = subprocess.run(['docker-compose', 'up', '-d'],
capture_output=True, text=True, check=True)
print("โœ… ์„œ๋น„์Šค ์‹œ์ž‘ ์„ฑ๊ณต")
return True
except subprocess.CalledProcessError as e:
print(f"โŒ ์„œ๋น„์Šค ์‹œ์ž‘ ์‹คํŒจ: {e.stderr}")
return False
def check_service_status():
"""์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ"""
try:
result = subprocess.run(['docker-compose', 'ps'],
capture_output=True, text=True, check=True)
print("๐Ÿ“Š ์„œ๋น„์Šค ์ƒํƒœ:")
print(result.stdout)
return True
except subprocess.CalledProcessError as e:
print(f"โŒ ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ ์‹คํŒจ: {e.stderr}")
return False
def wait_for_api_ready(max_wait=60):
"""API ์ค€๋น„ ๋Œ€๊ธฐ"""
print("โณ API ์ค€๋น„ ๋Œ€๊ธฐ ์ค‘...")
for i in range(max_wait):
try:
response = requests.get('http://localhost:8001/health', timeout=5)
if response.status_code == 200:
print(f"โœ… API ์ค€๋น„ ์™„๋ฃŒ ({i+1}์ดˆ)")
return True
except requests.exceptions.RequestException:
pass
time.sleep(1)
print("โŒ API ์ค€๋น„ ์‹œ๊ฐ„ ์ดˆ๊ณผ")
return False
def test_api_endpoints():
"""API ์—”๋“œํฌ์ธํŠธ ํ…Œ์ŠคํŠธ"""
endpoints = [
('/health', 'GET'),
('/models', 'GET'),
('/generate', 'POST')
]
print("๐Ÿงช API ์—”๋“œํฌ์ธํŠธ ํ…Œ์ŠคํŠธ:")
for endpoint, method in endpoints:
try:
if method == 'GET':
response = requests.get(f'http://localhost:8001{endpoint}', timeout=10)
elif method == 'POST' and endpoint == '/generate':
# ๊ฐ„๋‹จํ•œ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ
data = {
'prompt': '์•ˆ๋…•ํ•˜์„ธ์š”',
'model_id': 'polyglot-ko-1.3b-chat',
'max_length': 50,
'temperature': 0.7
}
response = requests.post(f'http://localhost:8001{endpoint}',
data=data, timeout=30)
else:
continue
if response.status_code in [200, 201]:
print(f"โœ… {endpoint} - {response.status_code}")
else:
print(f"โš ๏ธ {endpoint} - {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"โŒ {endpoint} - ์˜ค๋ฅ˜: {e}")
def test_redis_connection():
"""Redis ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ"""
try:
result = subprocess.run(['docker-compose', 'exec', '-T', 'redis', 'redis-cli', 'ping'],
capture_output=True, text=True, check=True)
if 'PONG' in result.stdout:
print("โœ… Redis ์—ฐ๊ฒฐ ์„ฑ๊ณต")
return True
else:
print("โŒ Redis ์—ฐ๊ฒฐ ์‹คํŒจ")
return False
except subprocess.CalledProcessError:
print("โŒ Redis ์—ฐ๊ฒฐ ์‹คํŒจ")
return False
def test_celery_worker():
"""Celery Worker ํ…Œ์ŠคํŠธ"""
try:
result = subprocess.run(['docker-compose', 'exec', '-T', 'celery-worker', 'celery', '-A', 'lily_llm_core.celery_app', 'inspect', 'active'],
capture_output=True, text=True, check=True)
print("โœ… Celery Worker ์ •์ƒ")
return True
except subprocess.CalledProcessError:
print("โš ๏ธ Celery Worker ํ™•์ธ ์‹คํŒจ (์ •์ƒ์ผ ์ˆ˜ ์žˆ์Œ)")
return True
def check_flower_monitoring():
"""Flower ๋ชจ๋‹ˆํ„ฐ๋ง ํ™•์ธ"""
try:
response = requests.get('http://localhost:5555', timeout=5)
if response.status_code == 200:
print("โœ… Flower ๋ชจ๋‹ˆํ„ฐ๋ง ์ ‘๊ทผ ๊ฐ€๋Šฅ")
return True
else:
print("โš ๏ธ Flower ๋ชจ๋‹ˆํ„ฐ๋ง ์ ‘๊ทผ ๋ถˆ๊ฐ€")
return False
except requests.exceptions.RequestException:
print("โš ๏ธ Flower ๋ชจ๋‹ˆํ„ฐ๋ง ์ ‘๊ทผ ๋ถˆ๊ฐ€")
return False
def stop_services():
"""์„œ๋น„์Šค ์ค‘์ง€"""
try:
print("๐Ÿ›‘ ์„œ๋น„์Šค ์ค‘์ง€ ์ค‘...")
subprocess.run(['docker-compose', 'down'],
capture_output=True, text=True, check=True)
print("โœ… ์„œ๋น„์Šค ์ค‘์ง€ ์™„๋ฃŒ")
return True
except subprocess.CalledProcessError as e:
print(f"โŒ ์„œ๋น„์Šค ์ค‘์ง€ ์‹คํŒจ: {e.stderr}")
return False
def cleanup():
"""์ •๋ฆฌ"""
try:
print("๐Ÿงน ์ •๋ฆฌ ์ค‘...")
subprocess.run(['docker-compose', 'down', '-v'],
capture_output=True, text=True, check=True)
subprocess.run(['docker', 'system', 'prune', '-f'],
capture_output=True, text=True, check=True)
print("โœ… ์ •๋ฆฌ ์™„๋ฃŒ")
return True
except subprocess.CalledProcessError as e:
print(f"โŒ ์ •๋ฆฌ ์‹คํŒจ: {e.stderr}")
return False
def main():
"""๋ฉ”์ธ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜"""
print("๐Ÿณ Docker ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์‹œ์ž‘")
print("=" * 50)
# 1. ์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ ํ™•์ธ
print("\n๐Ÿ“‹ ์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ ํ™•์ธ")
print("-" * 30)
if not check_docker_installation():
return False
if not check_docker_compose_installation():
return False
if not check_dockerfile():
return False
if not check_docker_compose_file():
return False
# 2. Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ
print("\n๐Ÿ”จ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ")
print("-" * 30)
if not build_docker_image():
return False
# 3. ์„œ๋น„์Šค ์‹œ์ž‘
print("\n๐Ÿš€ ์„œ๋น„์Šค ์‹œ์ž‘")
print("-" * 30)
if not start_services():
return False
# 4. ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ
print("\n๐Ÿ“Š ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ")
print("-" * 30)
check_service_status()
# 5. API ์ค€๋น„ ๋Œ€๊ธฐ
print("\nโณ API ์ค€๋น„ ๋Œ€๊ธฐ")
print("-" * 30)
if not wait_for_api_ready():
print("โŒ API ์ค€๋น„ ์‹คํŒจ")
stop_services()
return False
# 6. API ์—”๋“œํฌ์ธํŠธ ํ…Œ์ŠคํŠธ
print("\n๐Ÿงช API ์—”๋“œํฌ์ธํŠธ ํ…Œ์ŠคํŠธ")
print("-" * 30)
test_api_endpoints()
# 7. Redis ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ
print("\n๐Ÿ”ด Redis ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ")
print("-" * 30)
test_redis_connection()
# 8. Celery Worker ํ…Œ์ŠคํŠธ
print("\n๐ŸŒฟ Celery Worker ํ…Œ์ŠคํŠธ")
print("-" * 30)
test_celery_worker()
# 9. Flower ๋ชจ๋‹ˆํ„ฐ๋ง ํ™•์ธ
print("\n๐ŸŒธ Flower ๋ชจ๋‹ˆํ„ฐ๋ง ํ™•์ธ")
print("-" * 30)
check_flower_monitoring()
# 10. ๊ฒฐ๊ณผ ์š”์•ฝ
print("\n๐Ÿ“Š ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ์š”์•ฝ")
print("-" * 30)
print("โœ… Docker ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ!")
print("\n๐ŸŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค:")
print(" - API Server: http://localhost:8001")
print(" - Health Check: http://localhost:8001/health")
print(" - Flower Monitor: http://localhost:5555")
print("\n๐Ÿ“ ์œ ์šฉํ•œ ๋ช…๋ น์–ด:")
print(" - ๋กœ๊ทธ ํ™•์ธ: docker-compose logs")
print(" - ์„œ๋น„์Šค ์ƒํƒœ: docker-compose ps")
print(" - ์„œ๋น„์Šค ์ค‘์ง€: docker-compose down")
print(" - ์ •๋ฆฌ: docker-compose down -v && docker system prune -f")
return True
if __name__ == "__main__":
try:
success = main()
if not success:
print("\nโŒ Docker ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์‹คํŒจ")
sys.exit(1)
else:
print("\n๐ŸŽ‰ Docker ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต!")
except KeyboardInterrupt:
print("\nโš ๏ธ ์‚ฌ์šฉ์ž์— ์˜ํ•ด ์ค‘๋‹จ๋จ")
stop_services()
sys.exit(1)
except Exception as e:
print(f"\nโŒ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜: {e}")
stop_services()
sys.exit(1)