feat(docker): Docker 컨테이너 환경 구성
[파일 목록] - Dockerfile: GUARDiA ITSM Python 3.11-slim 이미지 - 비루트(guardia) 계정 실행 - 헬스체크 내장 - docker-compose.yml: 개발/테스트 풀스택 - guardia-itsm, nginx, postgres:15, redis:7, ollama/ollama, tomcat:9 - Ollama 모델은 볼륨 마운트 (이미지 외부) - docker-compose.prod.yml: 운영 환경 오버라이드 - 외부 포트 차단, 호스트 경로 마운트 - docker-compose.gpu.yml: NVIDIA GPU 오버라이드 - docker-start.sh: dev|prod|gpu 모드 빠른 시작 - .dockerignore: 보안 파일(.env, *.db) 제외 - docker/nginx/guardia.conf: 리버스 프록시 설정 - docker/tomcat/tomcat-users.xml: opsagent 계정 설정 [폐쇄망 패키지] - setup/docker_package.sh: 인터넷 서버에서 모든 이미지를 tar.gz로 패키징 - setup/docker_load.sh: 폐쇄망에서 tar.gz 로드 + 즉시 시작 옵션 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a899dc208a
commit
eea643ce40
63
.dockerignore
Normal file
63
.dockerignore
Normal file
@ -0,0 +1,63 @@
|
||||
# Git
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.pytest_cache/
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
.eggs/
|
||||
venv/
|
||||
.venv/
|
||||
env/
|
||||
|
||||
# 개발 도구
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# 테스트
|
||||
tests/
|
||||
test_*.py
|
||||
*.test.py
|
||||
|
||||
# 문서/설정
|
||||
docs/
|
||||
manual/
|
||||
*.md
|
||||
*.txt
|
||||
!requirements.txt
|
||||
|
||||
# 데이터
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
guardia_itsm.db*
|
||||
|
||||
# 업로드
|
||||
uploads/
|
||||
*.log
|
||||
|
||||
# 환경 파일 (보안)
|
||||
.env
|
||||
.env.*
|
||||
*.env
|
||||
secrets/
|
||||
|
||||
# Docker 패키지
|
||||
docker-package/
|
||||
|
||||
# 설치 스크립트
|
||||
setup/
|
||||
|
||||
# workspace
|
||||
workspace/
|
||||
|
||||
# Claude
|
||||
.claude/
|
||||
54
Dockerfile
Normal file
54
Dockerfile
Normal file
@ -0,0 +1,54 @@
|
||||
# ============================================================
|
||||
# GUARDiA ITSM — Production Dockerfile
|
||||
# Base: Python 3.11-slim
|
||||
# Port: 8001
|
||||
# ============================================================
|
||||
|
||||
FROM python:3.11-slim AS base
|
||||
|
||||
LABEL maintainer="GUARDiA Team"
|
||||
LABEL description="GUARDiA ITSM — AI 기반 레거시 인프라 자율 운영 플랫폼"
|
||||
|
||||
# ── 시스템 의존성 ──────────────────────────────────────────
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl wget git \
|
||||
libpq-dev gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ── 비루트 실행 계정 ───────────────────────────────────────
|
||||
RUN groupadd -r guardia && useradd -r -g guardia -d /app guardia
|
||||
|
||||
# ── 작업 디렉토리 ─────────────────────────────────────────
|
||||
WORKDIR /app
|
||||
|
||||
# ── Python 의존성 (레이어 캐싱 최적화) ─────────────────────
|
||||
COPY itsm/requirements.txt .
|
||||
RUN pip install --no-cache-dir --upgrade pip \
|
||||
&& pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# ── 애플리케이션 소스 복사 ───────────────────────────────
|
||||
COPY itsm/ .
|
||||
|
||||
# ── 업로드/데이터 디렉토리 ──────────────────────────────
|
||||
RUN mkdir -p uploads/sr_files uploads/workspaces \
|
||||
&& chown -R guardia:guardia /app
|
||||
|
||||
# ── 환경 기본값 ──────────────────────────────────────────
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONIOENCODING=utf-8 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
DATABASE_URL="sqlite+aiosqlite:///./guardia_itsm.db" \
|
||||
OLLAMA_BASE_URL="http://ollama:11434"
|
||||
|
||||
# ── 포트 노출 ────────────────────────────────────────────
|
||||
EXPOSE 8001
|
||||
|
||||
# ── 비루트 전환 ─────────────────────────────────────────
|
||||
USER guardia
|
||||
|
||||
# ── 헬스체크 ─────────────────────────────────────────────
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
||||
CMD curl -sf http://localhost:8001/ || exit 1
|
||||
|
||||
# ── 엔트리포인트 ─────────────────────────────────────────
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001", "--workers", "4"]
|
||||
23
docker-compose.gpu.yml
Normal file
23
docker-compose.gpu.yml
Normal file
@ -0,0 +1,23 @@
|
||||
# ============================================================
|
||||
# GUARDiA — NVIDIA GPU 오버라이드 (Ollama 가속)
|
||||
# ============================================================
|
||||
# 사용법:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d ollama
|
||||
#
|
||||
# 전제조건:
|
||||
# - nvidia-container-toolkit 설치 완료
|
||||
# - nvidia-smi 정상 작동 확인
|
||||
# ============================================================
|
||||
|
||||
services:
|
||||
ollama:
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
environment:
|
||||
OLLAMA_HOST: 0.0.0.0
|
||||
CUDA_VISIBLE_DEVICES: "0"
|
||||
46
docker-compose.prod.yml
Normal file
46
docker-compose.prod.yml
Normal file
@ -0,0 +1,46 @@
|
||||
# ============================================================
|
||||
# GUARDiA ITSM — 운영 환경 오버라이드
|
||||
# ============================================================
|
||||
# 사용법:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
# ============================================================
|
||||
|
||||
services:
|
||||
|
||||
guardia:
|
||||
image: guardia-itsm:${GUARDIA_VERSION:-latest}
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL} # 운영 DB URL 필수
|
||||
SECRET_KEY: ${SECRET_KEY} # 운영 시크릿 키 필수
|
||||
ports:
|
||||
- "127.0.0.1:8001:8001" # localhost만 — Nginx를 통해서만 외부 접근
|
||||
volumes:
|
||||
- /data/guardia/uploads:/app/uploads # 호스트 경로 직접 마운트
|
||||
- /data/guardia/logs:/app/logs
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
max_attempts: 3
|
||||
resources:
|
||||
limits:
|
||||
cpus: "2.0"
|
||||
memory: 2G
|
||||
|
||||
postgres:
|
||||
ports: [] # 운영에서는 외부 노출 금지
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
|
||||
redis:
|
||||
ports: [] # 운영에서는 외부 노출 금지
|
||||
|
||||
ollama:
|
||||
ports:
|
||||
- "127.0.0.1:11434:11434" # localhost만 노출
|
||||
volumes:
|
||||
- ${OLLAMA_MODELS_PATH:-/data/ollama}:/root/.ollama
|
||||
|
||||
tomcat:
|
||||
ports:
|
||||
- "127.0.0.1:8080:8080" # localhost만
|
||||
196
docker-compose.yml
Normal file
196
docker-compose.yml
Normal file
@ -0,0 +1,196 @@
|
||||
# ============================================================
|
||||
# GUARDiA ITSM — Full Stack docker-compose (개발/테스트용)
|
||||
# ============================================================
|
||||
# 사용법:
|
||||
# docker compose up -d # 전체 스택 시작
|
||||
# docker compose up -d guardia # GUARDiA만 시작 (DB/Redis는 외부)
|
||||
# docker compose logs -f guardia
|
||||
# docker compose down -v # 볼륨 포함 완전 삭제
|
||||
#
|
||||
# 환경변수:
|
||||
# .env 파일에 GUARDIA_LICENSE_KEY, SECRET_KEY 등을 설정하세요.
|
||||
# (itsm/.env가 없으면 기본값 사용)
|
||||
# ============================================================
|
||||
|
||||
x-common-env: &common-env
|
||||
PYTHONIOENCODING: utf-8
|
||||
PYTHONUNBUFFERED: "1"
|
||||
DATABASE_URL: postgresql+asyncpg://guardia:guardia@postgres:5432/guardia
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
OLLAMA_BASE_URL: http://ollama:11434
|
||||
MESSENGER_BASE_URL: http://messenger:8002
|
||||
MESSENGER_OPS_ROOM: ops
|
||||
|
||||
services:
|
||||
|
||||
# ── GUARDiA ITSM ────────────────────────────────────────
|
||||
guardia:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: guardia-itsm:latest
|
||||
container_name: guardia-itsm
|
||||
ports:
|
||||
- "8001:8001"
|
||||
environment:
|
||||
<<: *common-env
|
||||
SECRET_KEY: ${SECRET_KEY:-change_this_in_production_min_32chars}
|
||||
ALGORITHM: HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: 480
|
||||
GUARDIA_LLM_MODEL: ${GUARDIA_LLM_MODEL:-llama3.1:8b}
|
||||
GUARDIA_LICENSE_KEY: ${GUARDIA_LICENSE_KEY:-}
|
||||
# OAuth 소셜 로그인 (선택)
|
||||
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
|
||||
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
|
||||
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-}
|
||||
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-}
|
||||
KEYCLOAK_BASE_URL: ${KEYCLOAK_BASE_URL:-}
|
||||
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-master}
|
||||
KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID:-guardia}
|
||||
KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET:-}
|
||||
CATALINA_HOME: /app/tomcat
|
||||
volumes:
|
||||
- guardia-uploads:/app/uploads
|
||||
- guardia-db:/app # SQLite 개발 모드용 (PostgreSQL 사용 시 불필요)
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-sf", "http://localhost:8001/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# ── Nginx 리버스 프록시 ──────────────────────────────────
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: guardia-nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./docker/nginx/guardia.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./docker/nginx/ssl:/etc/nginx/ssl:ro # HTTPS 인증서 (선택)
|
||||
depends_on:
|
||||
- guardia
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
|
||||
# ── PostgreSQL ───────────────────────────────────────────
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: guardia-postgres
|
||||
environment:
|
||||
POSTGRES_DB: guardia
|
||||
POSTGRES_USER: guardia
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-guardia}
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- guardia-pgdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432" # 개발용 노출 (운영에서는 제거)
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U guardia -d guardia"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# ── Redis ────────────────────────────────────────────────
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: guardia-redis
|
||||
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
- guardia-redis:/data
|
||||
ports:
|
||||
- "6379:6379" # 개발용 노출
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
# ── Ollama (온프레미스 sLLM) ─────────────────────────────
|
||||
# 모델은 볼륨(guardia-ollama-models)에 저장 — 이미지에 포함 안 함
|
||||
# GPU 지원: docker-compose.gpu.yml 오버라이드 파일 참조
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
container_name: guardia-ollama
|
||||
volumes:
|
||||
- guardia-ollama-models:/root/.ollama # 모델 영구 저장
|
||||
ports:
|
||||
- "11434:11434" # 내부 전용 (외부 노출 금지 권장)
|
||||
environment:
|
||||
OLLAMA_HOST: 0.0.0.0
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
# GPU 사용 시 아래 주석 해제 (docker-compose.gpu.yml에서 override)
|
||||
# deploy:
|
||||
# resources:
|
||||
# reservations:
|
||||
# devices:
|
||||
# - driver: nvidia
|
||||
# count: 1
|
||||
# capabilities: [gpu]
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-sf", "http://localhost:11434/api/version"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
# ── Tomcat 9 (WAS 환경 시뮬레이션) ──────────────────────
|
||||
tomcat:
|
||||
image: tomcat:9.0-jdk17-temurin-jammy
|
||||
container_name: guardia-tomcat
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- guardia-tomcat-webapps:/usr/local/tomcat/webapps
|
||||
- guardia-tomcat-logs:/usr/local/tomcat/logs
|
||||
- ./docker/tomcat/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml:ro
|
||||
environment:
|
||||
JAVA_OPTS: "-Xms512m -Xmx1024m -Djava.awt.headless=true"
|
||||
CATALINA_OPTS: "-server -XX:+UseParallelGC"
|
||||
networks:
|
||||
- guardia-net
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-sf", "http://localhost:8080/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# ── 볼륨 ─────────────────────────────────────────────────
|
||||
volumes:
|
||||
guardia-db:
|
||||
guardia-uploads:
|
||||
guardia-pgdata:
|
||||
guardia-redis:
|
||||
guardia-ollama-models: # Ollama 모델 (로컬 경로 마운트 가능)
|
||||
guardia-tomcat-webapps:
|
||||
guardia-tomcat-logs:
|
||||
|
||||
# ── 네트워크 ──────────────────────────────────────────────
|
||||
networks:
|
||||
guardia-net:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.20.0.0/16
|
||||
33
docker-start.sh
Normal file
33
docker-start.sh
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
# GUARDiA 빠른 시작 스크립트
|
||||
# 사용법: bash docker-start.sh [dev|prod|gpu]
|
||||
|
||||
MODE="${1:-dev}"
|
||||
|
||||
case "$MODE" in
|
||||
dev)
|
||||
echo "▶ 개발 모드 시작..."
|
||||
docker compose up -d
|
||||
;;
|
||||
prod)
|
||||
echo "▶ 운영 모드 시작..."
|
||||
[[ -f ".env" ]] || { echo "❌ .env 파일이 없습니다. .env.example을 복사하세요."; exit 1; }
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
;;
|
||||
gpu)
|
||||
echo "▶ GPU 모드 시작 (Ollama NVIDIA 가속)..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d
|
||||
;;
|
||||
*)
|
||||
echo "사용법: bash docker-start.sh [dev|prod|gpu]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "서비스 상태:"
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "접속: http://localhost"
|
||||
echo "로그: docker compose logs -f guardia"
|
||||
44
docker/nginx/guardia.conf
Normal file
44
docker/nginx/guardia.conf
Normal file
@ -0,0 +1,44 @@
|
||||
upstream guardia_backend {
|
||||
server guardia:8001;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
client_max_body_size 100M;
|
||||
|
||||
# GUARDiA ITSM
|
||||
location / {
|
||||
proxy_pass http://guardia_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
# 정적 파일 직접 서빙 (선택 최적화)
|
||||
# location /static/ {
|
||||
# alias /app/static/;
|
||||
# expires 1d;
|
||||
# add_header Cache-Control "public";
|
||||
# }
|
||||
|
||||
# Ollama/Tomcat 직접 노출 금지
|
||||
location /api/ollama/ { return 403; }
|
||||
location /manager/ { return 403; }
|
||||
}
|
||||
|
||||
# HTTPS (인증서 설정 후 활성화)
|
||||
# server {
|
||||
# listen 443 ssl http2;
|
||||
# server_name guardia.example.com;
|
||||
# ssl_certificate /etc/nginx/ssl/cert.pem;
|
||||
# ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||||
# ssl_protocols TLSv1.2 TLSv1.3;
|
||||
# include /etc/nginx/conf.d/guardia.conf; # location 블록 재사용
|
||||
# }
|
||||
23
docker/tomcat/tomcat-users.xml
Normal file
23
docker/tomcat/tomcat-users.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tomcat-users xmlns="http://tomcat.apache.org/xml"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
|
||||
version="1.0">
|
||||
|
||||
<!-- GUARDiA SSH 원격 관리용 계정 -->
|
||||
<role rolename="manager-script"/>
|
||||
<role rolename="manager-jmx"/>
|
||||
<role rolename="manager-gui"/>
|
||||
<role rolename="admin-gui"/>
|
||||
|
||||
<!-- opsagent: GUARDiA ITSM 배포/재기동 자동화 계정 -->
|
||||
<!-- 운영 환경에서는 반드시 비밀번호를 변경하세요 -->
|
||||
<user username="opsagent"
|
||||
password="Opsagent@guardia!"
|
||||
roles="manager-script,manager-jmx"/>
|
||||
|
||||
<!-- admin: Tomcat Manager UI (개발용) -->
|
||||
<user username="admin"
|
||||
password="Admin@guardia!"
|
||||
roles="manager-gui,admin-gui"/>
|
||||
</tomcat-users>
|
||||
149
setup/docker_load.sh
Normal file
149
setup/docker_load.sh
Normal file
@ -0,0 +1,149 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# GUARDiA Docker 폐쇄망 로드 스크립트
|
||||
# ============================================================
|
||||
# docker_package.sh 로 생성된 패키지를 폐쇄망 서버에서 로드합니다.
|
||||
#
|
||||
# 사용법:
|
||||
# tar -xzf guardia-docker-YYYYMMDD.tar.gz
|
||||
# cd guardia-docker-YYYYMMDD
|
||||
# bash docker_load.sh
|
||||
# bash docker_load.sh --start # 로드 후 즉시 서비스 시작
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
START_AFTER="${1:-}"
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
||||
info() { echo -e " $*"; }
|
||||
|
||||
echo "=================================================="
|
||||
echo " GUARDiA Docker 폐쇄망 로드"
|
||||
echo " 디렉토리: $SCRIPT_DIR"
|
||||
echo "=================================================="
|
||||
|
||||
# Docker 설치 확인
|
||||
command -v docker &>/dev/null || fail "Docker가 설치되지 않았습니다. Docker Engine을 먼저 설치하세요."
|
||||
docker compose version &>/dev/null || fail "Docker Compose가 필요합니다. (docker compose 플러그인)"
|
||||
|
||||
# ── 1. 버전 정보 확인 ───────────────────────────────────
|
||||
if [[ -f "$SCRIPT_DIR/VERSION" ]]; then
|
||||
source "$SCRIPT_DIR/VERSION"
|
||||
echo " 패키지 버전: ${GUARDIA_VERSION:-unknown}"
|
||||
echo " 빌드 일자: ${BUILD_DATE:-unknown}"
|
||||
fi
|
||||
|
||||
# ── 2. 이미지 로드 ──────────────────────────────────────
|
||||
echo ""
|
||||
echo "[1/4] Docker 이미지 로드..."
|
||||
|
||||
# 메인 이미지
|
||||
if [[ -f "$SCRIPT_DIR/images.tar.gz" ]]; then
|
||||
echo " 로드 중: images.tar.gz"
|
||||
docker load < "$SCRIPT_DIR/images.tar.gz"
|
||||
ok "메인 이미지 로드 완료"
|
||||
else
|
||||
fail "images.tar.gz 파일을 찾을 수 없습니다."
|
||||
fi
|
||||
|
||||
# Ollama 이미지
|
||||
if [[ -f "$SCRIPT_DIR/ollama.tar.gz" ]]; then
|
||||
echo " 로드 중: ollama.tar.gz (시간이 걸릴 수 있습니다...)"
|
||||
docker load < "$SCRIPT_DIR/ollama.tar.gz"
|
||||
ok "Ollama 이미지 로드 완료"
|
||||
else
|
||||
warn "ollama.tar.gz 없음 — Ollama 이미지 로드 건너뜀"
|
||||
fi
|
||||
|
||||
# 로드된 이미지 목록 출력
|
||||
echo ""
|
||||
echo " 로드된 이미지:"
|
||||
docker images | grep -E "guardia|postgres|redis|nginx|ollama|tomcat" | awk '{printf " %-40s %-15s %s\n", $1, $2, $7}'
|
||||
|
||||
# ── 3. Ollama 모델 복사 ─────────────────────────────────
|
||||
echo ""
|
||||
echo "[2/4] Ollama 모델 설정..."
|
||||
MODELS_TAR="$SCRIPT_DIR/ollama-models/models.tar.gz"
|
||||
|
||||
if [[ -f "$MODELS_TAR" ]]; then
|
||||
OLLAMA_DATA="${OLLAMA_DATA_DIR:-/var/lib/guardia/ollama}"
|
||||
mkdir -p "$OLLAMA_DATA"
|
||||
echo " 모델 압축 해제: $OLLAMA_DATA"
|
||||
tar -xzf "$MODELS_TAR" -C "$OLLAMA_DATA"
|
||||
ok "Ollama 모델 복사 완료: $OLLAMA_DATA"
|
||||
export OLLAMA_MODELS_PATH="$OLLAMA_DATA"
|
||||
else
|
||||
warn "Ollama 모델 파일 없음"
|
||||
warn " 방법 1: docker compose up -d ollama && docker exec guardia-ollama ollama pull llama3.1:8b"
|
||||
warn " 방법 2: 모델 파일을 수동으로 /var/lib/guardia/ollama/models 에 복사"
|
||||
fi
|
||||
|
||||
# ── 4. 환경 파일 설정 ────────────────────────────────────
|
||||
echo ""
|
||||
echo "[3/4] 환경 파일 설정..."
|
||||
ENV_FILE="$SCRIPT_DIR/.env"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
cat > "$ENV_FILE" << 'ENVEOF'
|
||||
# GUARDiA Docker 환경 설정
|
||||
# 운영 배포 전 반드시 아래 값을 변경하세요!
|
||||
|
||||
SECRET_KEY=CHANGE_THIS_TO_RANDOM_32CHARS_MIN
|
||||
POSTGRES_PASSWORD=guardia_secure_pw
|
||||
GUARDIA_VERSION=latest
|
||||
GUARDIA_LLM_MODEL=llama3.1:8b
|
||||
|
||||
# Ollama 모델 경로 (폐쇄망 복사 경로)
|
||||
OLLAMA_MODELS_PATH=/var/lib/guardia/ollama
|
||||
ENVEOF
|
||||
warn ".env 파일 생성됨 — SECRET_KEY를 반드시 변경하세요: $ENV_FILE"
|
||||
else
|
||||
info ".env 파일 이미 존재"
|
||||
fi
|
||||
|
||||
# ── 5. 서비스 시작 ──────────────────────────────────────
|
||||
echo ""
|
||||
echo "[4/4] 서비스 준비 완료"
|
||||
|
||||
if [[ "$START_AFTER" == "--start" ]]; then
|
||||
echo " 서비스 시작 중..."
|
||||
cd "$SCRIPT_DIR"
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
|
||||
# 헬스체크 대기
|
||||
echo " 서비스 기동 대기 (최대 60초)..."
|
||||
for i in $(seq 1 12); do
|
||||
sleep 5
|
||||
if curl -sf http://localhost/ &>/dev/null; then
|
||||
ok "GUARDiA ITSM 서비스 정상 기동!"
|
||||
break
|
||||
fi
|
||||
echo " 대기 중... (${i}/12)"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo " 서비스 상태:"
|
||||
docker compose ps
|
||||
else
|
||||
echo ""
|
||||
info "서비스 시작 명령어:"
|
||||
info " cd $SCRIPT_DIR"
|
||||
info " # .env 파일 편집 후:"
|
||||
info " docker compose up -d"
|
||||
info " # 또는 운영 모드:"
|
||||
info " docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d"
|
||||
info ""
|
||||
info " # 즉시 시작:"
|
||||
info " bash docker_load.sh --start"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
ok "Docker 로드 완료!"
|
||||
info "접속 URL: http://$(hostname -I | awk '{print $1}')"
|
||||
info "GUARDiA 로그: docker compose logs -f guardia"
|
||||
echo "=================================================="
|
||||
147
setup/docker_package.sh
Normal file
147
setup/docker_package.sh
Normal file
@ -0,0 +1,147 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# GUARDiA Docker 폐쇄망 패키지 생성 스크립트
|
||||
# ============================================================
|
||||
# 인터넷이 연결된 서버에서 실행하여 모든 이미지를 tar로 패키징합니다.
|
||||
# 생성된 패키지를 USB/내부 서버를 통해 폐쇄망에 복사 후 docker_load.sh 실행.
|
||||
#
|
||||
# 사용법:
|
||||
# bash setup/docker_package.sh [출력 디렉토리]
|
||||
# bash setup/docker_package.sh /mnt/usb/guardia-docker
|
||||
#
|
||||
# 결과:
|
||||
# guardia-docker-<버전>.tar.gz (약 5~8GB — Ollama 모델 별도)
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GUARDIA_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
OUTPUT_DIR="${1:-$GUARDIA_ROOT/docker-package}"
|
||||
VERSION="${GUARDIA_VERSION:-$(date +%Y%m%d)}"
|
||||
PACKAGE_NAME="guardia-docker-${VERSION}"
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
info() { echo -e " $*"; }
|
||||
|
||||
echo "=================================================="
|
||||
echo " GUARDiA Docker 패키지 생성"
|
||||
echo " 버전: $VERSION"
|
||||
echo " 출력: $OUTPUT_DIR"
|
||||
echo "=================================================="
|
||||
|
||||
mkdir -p "$OUTPUT_DIR/$PACKAGE_NAME"
|
||||
cd "$GUARDIA_ROOT"
|
||||
|
||||
# ── 1. GUARDiA 이미지 빌드 ───────────────────────────────
|
||||
echo ""
|
||||
echo "[1/5] GUARDiA ITSM 이미지 빌드..."
|
||||
docker build -t "guardia-itsm:${VERSION}" -t "guardia-itsm:latest" .
|
||||
ok "guardia-itsm:${VERSION} 빌드 완료"
|
||||
|
||||
# ── 2. 외부 이미지 Pull ──────────────────────────────────
|
||||
echo ""
|
||||
echo "[2/5] 외부 이미지 다운로드..."
|
||||
|
||||
IMAGES=(
|
||||
"postgres:15-alpine"
|
||||
"redis:7-alpine"
|
||||
"nginx:alpine"
|
||||
"ollama/ollama:latest"
|
||||
"tomcat:9.0-jdk17-temurin-jammy"
|
||||
)
|
||||
|
||||
for img in "${IMAGES[@]}"; do
|
||||
echo " pulling: $img"
|
||||
docker pull "$img" || warn "$img 다운로드 실패 — 건너뜀"
|
||||
done
|
||||
ok "외부 이미지 다운로드 완료"
|
||||
|
||||
# ── 3. 이미지 tar 저장 ──────────────────────────────────
|
||||
echo ""
|
||||
echo "[3/5] 이미지 저장 (tar)..."
|
||||
TAR_FILE="$OUTPUT_DIR/$PACKAGE_NAME/images.tar"
|
||||
|
||||
docker save \
|
||||
"guardia-itsm:${VERSION}" \
|
||||
"guardia-itsm:latest" \
|
||||
"postgres:15-alpine" \
|
||||
"redis:7-alpine" \
|
||||
"nginx:alpine" \
|
||||
"tomcat:9.0-jdk17-temurin-jammy" \
|
||||
| gzip > "${TAR_FILE}.gz"
|
||||
|
||||
ok "이미지 저장 완료: ${TAR_FILE}.gz ($(du -sh "${TAR_FILE}.gz" | cut -f1))"
|
||||
|
||||
# Ollama는 용량이 크므로 별도 패키징
|
||||
OLLAMA_TAR="$OUTPUT_DIR/$PACKAGE_NAME/ollama.tar"
|
||||
docker save "ollama/ollama:latest" | gzip > "${OLLAMA_TAR}.gz"
|
||||
ok "Ollama 이미지 저장: ${OLLAMA_TAR}.gz ($(du -sh "${OLLAMA_TAR}.gz" | cut -f1))"
|
||||
|
||||
# ── 4. Ollama 모델 패키징 (선택) ──────────────────────────
|
||||
echo ""
|
||||
echo "[4/5] Ollama 모델 패키징..."
|
||||
OLLAMA_MODELS_DIR="${OLLAMA_MODELS_DIR:-$HOME/.ollama}"
|
||||
MODELS_OUTPUT="$OUTPUT_DIR/$PACKAGE_NAME/ollama-models"
|
||||
|
||||
if [[ -d "$OLLAMA_MODELS_DIR/models" ]]; then
|
||||
echo " 모델 디렉토리: $OLLAMA_MODELS_DIR"
|
||||
mkdir -p "$MODELS_OUTPUT"
|
||||
|
||||
# 각 모델을 개별 파일로 저장 (크기 분할)
|
||||
if command -v ollama &>/dev/null; then
|
||||
ollama list 2>/dev/null | tail -n +2 | awk '{print $1}' | while read -r model; do
|
||||
model_file="${model//:/--}.tar"
|
||||
echo " 패키징 모델: $model → $model_file"
|
||||
# 모델 블obs 복사
|
||||
mkdir -p "$MODELS_OUTPUT/$model_file"
|
||||
done
|
||||
fi
|
||||
|
||||
# 전체 모델 디렉토리 압축
|
||||
tar -czf "$MODELS_OUTPUT/models.tar.gz" -C "$OLLAMA_MODELS_DIR" models manifests 2>/dev/null \
|
||||
&& ok "Ollama 모델 패키징 완료 ($(du -sh "$MODELS_OUTPUT/models.tar.gz" | cut -f1))" \
|
||||
|| warn "모델 패키징 실패 — 수동으로 ~/.ollama/models 를 복사하세요"
|
||||
else
|
||||
warn "Ollama 모델 디렉토리 없음 — 별도 복사 필요: $OLLAMA_MODELS_DIR"
|
||||
echo " # 모델을 미리 다운로드: ollama pull llama3.1:8b"
|
||||
fi
|
||||
|
||||
# ── 5. 배포 파일 패키징 ──────────────────────────────────
|
||||
echo ""
|
||||
echo "[5/5] 배포 파일 패키징..."
|
||||
|
||||
# docker-compose 파일 복사
|
||||
cp "$GUARDIA_ROOT/docker-compose.yml" "$OUTPUT_DIR/$PACKAGE_NAME/"
|
||||
cp "$GUARDIA_ROOT/docker-compose.prod.yml" "$OUTPUT_DIR/$PACKAGE_NAME/"
|
||||
cp "$GUARDIA_ROOT/docker-compose.gpu.yml" "$OUTPUT_DIR/$PACKAGE_NAME/"
|
||||
cp "$GUARDIA_ROOT/setup/docker_load.sh" "$OUTPUT_DIR/$PACKAGE_NAME/"
|
||||
cp -r "$GUARDIA_ROOT/docker/" "$OUTPUT_DIR/$PACKAGE_NAME/docker/"
|
||||
chmod +x "$OUTPUT_DIR/$PACKAGE_NAME/docker_load.sh"
|
||||
|
||||
# 버전 정보
|
||||
cat > "$OUTPUT_DIR/$PACKAGE_NAME/VERSION" << VEREOF
|
||||
GUARDIA_VERSION=$VERSION
|
||||
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
IMAGES_INCLUDED=guardia-itsm,postgres,redis,nginx,tomcat,ollama
|
||||
VEREOF
|
||||
|
||||
# 전체 패키지 압축
|
||||
echo " 전체 패키지 압축 중..."
|
||||
cd "$OUTPUT_DIR"
|
||||
tar -czf "${PACKAGE_NAME}.tar.gz" "$PACKAGE_NAME/"
|
||||
ok "패키지 생성 완료: $OUTPUT_DIR/${PACKAGE_NAME}.tar.gz"
|
||||
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
ok "패키지 생성 완료!"
|
||||
echo ""
|
||||
info "패키지 크기:"
|
||||
du -sh "$OUTPUT_DIR/${PACKAGE_NAME}.tar.gz"
|
||||
echo ""
|
||||
info "폐쇄망 설치 절차:"
|
||||
info " 1. ${PACKAGE_NAME}.tar.gz 을 폐쇄망 서버로 복사"
|
||||
info " 2. tar -xzf ${PACKAGE_NAME}.tar.gz"
|
||||
info " 3. bash ${PACKAGE_NAME}/docker_load.sh"
|
||||
echo "=================================================="
|
||||
Loading…
Reference in New Issue
Block a user