From 558bfd9dbd6d17ff952dd76be595d8a5f70265b4 Mon Sep 17 00:00:00 2001 From: Jarca Date: Thu, 9 Jul 2026 19:12:09 +0900 Subject: [PATCH] deploy: add Streamlit dashboard service --- Dockerfile | 2 +- docker-compose.yml | 40 ++++++++++++++++++++++ docs/runbooks/docker-network-mcp-deploy.md | 22 +++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6137897..bd1d846 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN python -m pip install --upgrade pip \ && python -m pip install '.[dashboard]' VOLUME ["/data"] -EXPOSE 8000 +EXPOSE 8000 8501 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD python -c "import os, socket; s=socket.create_connection(('127.0.0.1', int(os.getenv('JARCA_MCP_PORT', '8000'))), timeout=3); s.close()" diff --git a/docker-compose.yml b/docker-compose.yml index 23a045a..7250f3b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,3 +17,43 @@ services: PYTHONUNBUFFERED: "1" volumes: - /volume1/docker/jarca-ledger/data:/data + + jarca-ledger-dashboard: + image: jarca-ledger:latest + container_name: jarca-ledger-dashboard + restart: unless-stopped + depends_on: + jarca-ledger: + condition: service_healthy + ports: + - "8501:8501" + environment: + JARCA_LEDGER_DB_PATH: /data/ledger.sqlite3 + STREAMLIT_BROWSER_GATHER_USAGE_STATS: "false" + PYTHONUNBUFFERED: "1" + volumes: + - /volume1/docker/jarca-ledger/data:/data + command: + - python + - -m + - streamlit + - run + - dashboard/app.py + - --server.address + - 0.0.0.0 + - --server.port + - "8501" + - --server.headless + - "true" + - --browser.gatherUsageStats + - "false" + healthcheck: + interval: 30s + timeout: 5s + start_period: 30s + retries: 3 + test: + - CMD + - python + - -c + - "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8501/_stcore/health', timeout=3).read()" diff --git a/docs/runbooks/docker-network-mcp-deploy.md b/docs/runbooks/docker-network-mcp-deploy.md index 7d9e676..7dbd1bd 100644 --- a/docs/runbooks/docker-network-mcp-deploy.md +++ b/docs/runbooks/docker-network-mcp-deploy.md @@ -2,13 +2,14 @@ ## 목적 -`jarca-ledger`를 `genichin-agent` 생명주기와 분리된 독립 Docker 서비스로 배포하고, stdio `docker exec`가 아니라 HTTP 기반 Streamable MCP endpoint를 직접 제공한다. +`jarca-ledger`를 `genichin-agent` 생명주기와 분리된 독립 Docker 서비스로 배포하고, stdio `docker exec`가 아니라 HTTP 기반 Streamable MCP endpoint를 직접 제공한다. 같은 이미지에서 별도 Streamlit 컨테이너(`jarca-ledger-dashboard`)를 실행해 운영 프론트엔드도 함께 서비스한다. ## 운영 고정값 | 항목 | 값 | |---|---| | 컨테이너 이름 | `jarca-ledger` | +| Streamlit 컨테이너 이름 | `jarca-ledger-dashboard` | | 이미지 | `jarca-ledger:latest` | | Host data path | `/volume1/docker/jarca-ledger/data` | | Container data path | `/data` | @@ -16,6 +17,7 @@ | MCP transport | `streamable-http` | | MCP listen | `0.0.0.0:8000` | | MCP path | `/mcp` | +| Streamlit listen | `0.0.0.0:8501` | ## 배포 @@ -29,8 +31,10 @@ docker compose up -d --build ```bash docker ps --filter name=jarca-ledger docker inspect jarca-ledger --format='MOUNTS: see HostConfig.Binds and Mounts in docker inspect output' +docker inspect jarca-ledger-dashboard --format='{{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' docker inspect jarca-ledger | python3 -c "import json,sys; data=json.load(sys.stdin)[0]; [print(f'{m.get(\"Source\")} -> {m.get(\"Destination\")} ({m.get(\"Type\")})') for m in data.get('Mounts', [])]" docker logs --tail 80 jarca-ledger +docker logs --tail 80 jarca-ledger-dashboard ``` Python MCP client smoke: @@ -54,9 +58,25 @@ anyio.run(main) PY ``` +Streamlit HTTP smoke: + +```bash +python - <<'PY' +import urllib.request + +for url in [ + 'http://127.0.0.1:8501/_stcore/health', + 'http://127.0.0.1:8501/?page=%EC%9A%94%EC%95%BD', +]: + with urllib.request.urlopen(url, timeout=10) as response: + print(url, response.status) +PY +``` + ## 운영 원칙 - `jarca-ledger` 컨테이너는 Docker daemon의 `restart: unless-stopped` 정책으로 독립 실행된다. +- `jarca-ledger-dashboard` 컨테이너는 같은 image와 `/data` volume을 사용하며, Streamlit UI를 `http://:8501`로 제공한다. - `genichin-agent`는 이 서비스를 배포하거나 실행시키는 필수 구성요소가 아니다. - 재무관리 에이전트는 `http://:8000/mcp` 또는 같은 Docker network에서 `http://jarca-ledger:8000/mcp`로 접속한다. - 운영 DB와 import 원본/민감자료는 이미지에 포함하지 않고 `/volume1/docker/jarca-ledger/data`에만 둔다.