Docker Compose 로 설치
설정 파일(/etc/geo-mlops/app.env) 생성, docker compose 로 스택 실행, 헬스체크 확인
MLOps Central Platform 은 소스 디렉터리의 docker-compose.yml 하나로 실행. 앱 이미지는 같은 디렉터리의 Dockerfile 로 빌드하고, Postgres·RustFS·Prometheus·Alertmanager·패키지 캐시가 함께 기동. 예시의 소스 경로는 /opt/geo-mlops. 파일 전문과 서비스·포트·볼륨 정리는 docker-compose.yml 레퍼런스 참고.
1. 설정 파일 만들기
앱의 비밀 설정은 소스 디렉터리 외부의 /etc/geo-mlops/app.env 에 저장. 소스를 새로 내려받거나 자동 배포가 소스 디렉터리를 정리해도 이 파일은 삭제되지 않음. 형식은 GEO_MLOPS_키=값 한 줄씩.
-
디렉터리와 파일 생성 후 권한 제한.
sudo install -d -m 0750 /etc/geo-mlops sudo install -m 0600 /dev/null /etc/geo-mlops/app.env -
서명 키·pepper·웹훅 토큰용으로 서로 다른 3개의 난수 생성.
openssl rand -hex 32 # GEO_MLOPS_AUTH_SECRET 용 openssl rand -hex 32 # GEO_MLOPS_EDGE_TOKEN_PEPPER 용 openssl rand -hex 32 # GEO_MLOPS_ALERTMANAGER_WEBHOOK_TOKEN 용 -
sudoedit /etc/geo-mlops/app.env로 아래 내용 입력.<your-secret>자리에 방금 만든 값을 입력하고, 주소는 실제 도메인으로 변경.
# --- 서명 키 (설치 직후 반드시 변경) ---------------------------------
GEO_MLOPS_AUTH_SECRET=<your-secret>
GEO_MLOPS_EDGE_TOKEN_PEPPER=<your-secret>
# --- 첫 전역 관리자 ----------------------------------------------------
GEO_MLOPS_RBAC_BOOTSTRAP_ADMIN_EMAIL=[email protected]
GEO_MLOPS_RBAC_BOOTSTRAP_ADMIN_PASSWORD=<your-secret>
# --- 개발용 시드 비활성화 (운영 설치에서는 반드시 비운다) ---------------------
GEO_MLOPS_RBAC_BOOTSTRAP_TENANTS=
GEO_MLOPS_RBAC_BOOTSTRAP_ROLE_PASSWORD=
# --- Alertmanager 웹훅 공유 비밀 ----------------------------------------
GEO_MLOPS_ALERTMANAGER_WEBHOOK_TOKEN=<your-secret>
# --- 접속 주소 ----------------------------------------------------------
# HTTPS 로 접속하면 true(기본값). 사내망에서 http:// 로만 쓴다면 false.
GEO_MLOPS_AUTH_COOKIE_SECURE=true
# 웹 화면이 다른 도메인에서 API 를 부를 때, 그 화면의 주소. 같은 도메인이면 비운다
GEO_MLOPS_CORS_ALLOW_ORIGINS=https://mlops.example.com
# MLflow 가 허용할 Host 헤더 (아래 설명 참고)
GEO_MLOPS_MLFLOW_ALLOWED_HOSTS=api.mlops.example.com,localhost:*,127.0.0.1:*,10.*
각 줄의 뜻과 바꾸지 않을 때의 위험은 필수 보안 설정 참고.
RBAC_BOOTSTRAP_TENANTS와RBAC_BOOTSTRAP_ROLE_PASSWORD를 비우는 이유: 기본값은 개발용. 비우지 않으면 첫 기동 때 개발용 테넌트와 역할별 데모 계정(비밀번호가 기본값) 생성. 시드는 기동 시마다 실행되므로, 나중에 그 테넌트를 삭제해도 다음 재시작 때 다시 생성. 첫 기동 전에 비워야 함. 테넌트는 설치 뒤 화면에서 생성.MLFLOW_ALLOWED_HOSTS: 내장 MLflow 는 DNS 리바인딩(주소를 속여 브라우저가 내부 서버에 요청하게 만드는 공격)을 차단하려고Host헤더 검사. 허용되지 않은 호스트에는 403 반환. 비우면 localhost 와 사설 IP(10.*, 192.168.* 등)만 통과. 값을 지정하면 이 기본 목록 전체가 대체되므로, 도메인과 함께localhost:*,127.0.0.1:*과 빌드 파드가 사용하는10.*도 포함 필요. 도메인으로 MLflow 를 사용하지 않으면 이 줄 생략 가능.
2. Alertmanager 웹훅 설정
monitoring/alertmanager.yml 에 Alertmanager 가 경보를 앱으로 전달하는 주소 기재. 앱은 GEO_MLOPS_ALERTMANAGER_WEBHOOK_TOKEN 이 비어 있으면 웹훅을 503 으로 거절하고, 값이 일치하지 않으면 401 반환. 두 곳 수정.
url의 포트가 앱 포트 10000 인지 확인. 배포본에:8000으로 적혀 있으면:10000으로 수정.- 주석 처리된
http_config.headers블록의 주석을 해제하고,app.env에 입력한 것과 같은 값 입력.
receivers:
- name: geo-mlops-webhook
webhook_configs:
- url: http://host.docker.internal:10000/api/v1/integrations/alertmanager/webhook
send_resolved: true
http_config:
headers:
X-Webhook-Token: <your-secret> # GEO_MLOPS_ALERTMANAGER_WEBHOOK_TOKEN 과 같은 값
3. 스택 실행
-
이미지 빌드 후 모든 서비스 실행. 첫 빌드는 인터넷에서 패키지를 내려받으므로 몇 분 소요.
docker compose -f /opt/geo-mlops/docker-compose.yml up -d --build --remove-orphans -
앱 컨테이너가
healthy가 될 때까지 대기(첫 기동은 30초 남짓).docker inspect --format='{{.State.Health.Status}}' geo-mlops-app docker compose -f /opt/geo-mlops/docker-compose.yml ps -
두 헬스체크 호출. 둘 다 인증 없이 호출 가능.
curl -s http://localhost:10000/api/v1/health # {"status":"ok","version":"…"} curl -s http://localhost:10000/api/v1/readyz # {"status":"ok","database":"up","object-store":"up","prometheus":"up","alertmanager":"up"}
/api/v1/health는 프로세스 동작 여부만 확인(의존 서비스에는 접속하지 않음). Compose 의 헬스체크가 사용./api/v1/readyz는 Postgres·오브젝트 저장소·Prometheus·Alertmanager 에 직접 접속해 확인. 하나라도down이면 전체가degraded. 로드밸런서의 준비 확인에 사용.degraded여도 상태 코드는 200 이므로 본문의status가ok인지 확인 필요.
서버 기동 후 http://<서버>:10000/docs 에서 API 문서 확인 가능.
4. 첫 기동 시 자동으로 수행되는 작업
따로 실행할 명령 없음. 앱 컨테이너의 start-uvicorn.sh 와 앱 시작 과정이 다음을 수행.
| 순서 | 하는 일 | 로그에서 확인 |
|---|---|---|
| 1 | DB 마이그레이션 alembic upgrade head (실패하면 서버가 기동되지 않음) | Running upgrade … |
| 2 | 공유 빌드 이미지 항목(학습 런타임·스테이저·서빙 빌더) 생성 | (따로 없음) |
| 3 | 부트스트랩 관리자 계정 생성 + 전역 관리자 권한 부여 | created bootstrap admin account [email protected] |
| 4 | 테넌트별 MLflow 워크스페이스 준비, 중단된 작업 정리 | (따로 없음) |
docker logs geo-mlops-app 2>&1 | grep -E "upgrade|bootstrap|seeded"
부트스트랩 관리자는 계정이 없을 때만 생성. 이미 있는 계정의 비밀번호는 변경하지 않음. 시드가 실패해도 서버는 기동되고, 실패 내용은 startup seeding failed 로 로그에 기록.
5. 앱 컨테이너의 메모리 상한
앱 컨테이너는 기본 16 GB 로 제한(초과하면 커널이 앱만 강제 종료하고, Compose 의 restart 설정이 다시 기동). GPU 가 시스템 메모리를 공유하는 장비에서 학습 파드가 사용할 메모리를 확보하기 위한 제한. 변경 시 Compose 실행 때 셸 변수로 지정.
GEO_APP_MEM_LIMIT=24g docker compose -f /opt/geo-mlops/docker-compose.yml up -d
이 값은 app.env 가 아니라 Compose 를 실행하는 셸에서 읽음. 업그레이드 등으로 up 을 다시 실행할 때도 함께 지정 필요. 생략하면 16 GB 로 되돌아감.
학습 파드는 이 상한과 별도로 GEO_MLOPS_TRAINING_RUNTIME_MEMORY_LIMIT(기본 64Gi)로 제한. 파드의 /dev/shm 도 이 상한에 포함. 초과하면 그 학습만 OOM 으로 종료되고 "메모리 부족(OOM)으로 종료되었습니다" 표시. 노드 메모리가 작으면 /etc/geo-mlops/app.env 에서 낮추고, 비우면 상한 없음.
6. 웹 화면 배포
웹 화면(프론트엔드)은 앱과 따로 배포하는 정적 파일 묶음. 빌드 시 API 주소를 번들에 포함(VITE_API_BASE_URL). 두 가지 배치 중 하나 선택.
| 배치 | 빌드 값 | 앱 설정 |
|---|---|---|
같은 도메인: 웹 서버가 정적 파일을 서빙하고 /api/·/auth/·/users/·/mlflow·/v2 를 10000 으로 전달 | VITE_API_BASE_URL= (비움) | GEO_MLOPS_CORS_ALLOW_ORIGINS= (비움. 기본값 * 는 시스템 진단에 경고로 표시됨) |
다른 도메인(예: 화면 https://mlops.example.com, API https://api.mlops.example.com) | VITE_API_BASE_URL=https://api.mlops.example.com | GEO_MLOPS_CORS_ALLOW_ORIGINS=https://mlops.example.com |
# 프론트엔드 소스 디렉터리에서
npm ci
VITE_API_BASE_URL=https://api.mlops.example.com npm run build # 결과: dist/
dist/ 를 정적 호스팅(웹 서버, CDN 등)에 배포. 화면 주소(/training, /system-health …)는 모두 브라우저 측 라우팅이므로, 없는 경로는 index.html 을 반환하도록(SPA fallback) 설정해야 새로고침해도 404 가 발생하지 않음. 같은 도메인 배치에서 API 경로는 끝 슬래시까지(/api/) 일치시켜 전달. 화면 주소 /api-services 도 /api 로 시작하므로, 슬래시 없이 접두사로 전달하면 그 화면 요청이 앱으로 전달되어 새로고침 때 404 발생.
7. 부속 서비스의 기본 계정
Compose 파일의 Postgres(mlflow/mlflow)와 RustFS(rustfsadmin/rustfsadmin) 계정은 파일에 고정, 포트(5433·9000·9001)는 서버의 모든 주소에 개방. Prometheus(9090)·Alertmanager(9093)·패키지 캐시(5000·3142)는 인증 없이 개방. 방화벽으로 이 포트들에 대한 외부 접근 차단 필요. 계정 변경 시 Compose 파일과 app.env 의 해당 설정(GEO_MLOPS_DATABASE_URL, GEO_MLOPS_MLFLOW_BACKEND_URI, GEO_MLOPS_MLFLOW_S3_ACCESS_KEY_ID, GEO_MLOPS_MLFLOW_S3_SECRET_ACCESS_KEY)과 백업 설정도 함께 변경.
자주 사용하는 명령
C="docker compose -f /opt/geo-mlops/docker-compose.yml"
$C ps # 상태
$C logs -f --tail=100 app # 앱 로그
$C up -d app # app.env 를 고친 뒤: 설정을 다시 읽어 앱만 재생성
$C down # 멈춤 (데이터 유지)
다음: k3s·GPU 준비