콘텐츠로 이동

Docker, Compose, 원클릭 PaaS

Distroless/Debian 이미지, Compose 배포, 헬스 체크, Podman, 그리고 Coolify/Dokploy/EasyPanel 템플릿.

Revka는 단일 자급자족 바이너리로 배포되므로 컨테이너 환경에 자연스럽게 적합합니다. 이 페이지에서는 Docker에서 Revka를 실행하는 방법을 다룹니다. 공개된 두 가지 이미지, 프로덕션용 docker-compose.yml, 컨테이너 환경 변수 레퍼런스, HEALTHCHECK 프로브, Podman 차이점, 그리고 세 가지 원클릭 PaaS 템플릿(Coolify, Dokploy, EasyPanel)과 각 릴리스와의 동기화 워크플로를 설명합니다.

서버 또는 PaaS 호스트에서 Revka를 장기 실행 게이트웨이로 운용하려는 경우 이 페이지를 참고하세요. 호스트의 OS init 시스템으로 직접 Revka를 관리하려면 백그라운드 서비스로 실행을 참고하세요. 컨테이너 내부 runtime.kind 샌드박스와 호스트 런타임의 차이에 대해서는 런타임 모드, 어댑터 및 리소스 제한을 참고하세요.

두 가지 멀티 아키텍처 이미지가 GitHub Container Registry에 게시됩니다. 동일한 빌드를 공유하지만 런타임 베이스가 다릅니다.

이미지베이스사용 시점
ghcr.io/kumihoio/revka:latestgcr.io/distroless/cc-debian13:nonroot없음공격 표면을 최소화하고 에이전트가 셸 도구를 필요로 하지 않는 경우.
ghcr.io/kumihoio/revka:debiandebian:bookworm-slim (bash, git, curl, ca-certificates 포함)있음에이전트가 셸 기반 도구(ls, git, curl 등)를 필요로 하는 경우.

두 이미지 모두 동일한 엔트리포인트를 사용합니다. revka daemon을 실행하며, 이는 게이트웨이, 채널, 하트비트, 스케줄러를 하나의 감독 프로세스 아래 통합한 완전 자율 런타임입니다. 두 이미지 모두 비권한 사용자 nobody(UID 65534)로 실행되고, 포트 42617을 노출하며, HOME=/revka-data와 워크스페이스 경로 /revka-data/workspace를 설정합니다.

런타임에 API 키를 제공하고, /revka-data를 명명된 볼륨에 유지하며, 게이트웨이 포트를 게시합니다.

Terminal window
docker run -d \
--name revka \
-e API_KEY=sk-or-... \
-e PROVIDER=openrouter \
-v revka-data:/revka-data \
-p 42617:42617 \
ghcr.io/kumihoio/revka:latest

이후 http://localhost:42617/에서 대시보드를 열 수 있습니다. 이미지에는 allow_public_bind = truerequire_pairing = false가 설정된 기본 config가 내장되어 있어 컨테이너 외부에서 즉시 게이트웨이에 접근할 수 있습니다.

두 Dockerfile 모두 컴파일할 Cargo 기능 플래그를 제어하는 단일 빌드 인수를 허용합니다.

Build ARG기본값의미
REVKA_CARGO_FEATURESchannel-lark,whatsapp-webcargo build --release --locked --features에 전달되는 쉼표로 구분된 Cargo 기능 목록. 기본 기능 세트만 빌드하려면 빈 값으로 설정하세요.
Terminal window
# Build the distroless image with a custom feature set
docker build --build-arg REVKA_CARGO_FEATURES="channel-lark" -t revka:custom .
# Build the Debian (shell-equipped) variant
docker build -f Dockerfile.debian -t revka:debian .

빌드는 멀티 스테이지 파이프라인입니다. web-builder 스테이지(Node 22 Alpine)에서 대시보드를 컴파일하고, builder 스테이지(Rust 1.95)에서 레지스트리/타겟 빌드 캐시를 사용하여 바이너리를 컴파일하며, 최종 스테이지에서 스트립된 바이너리를 distroless 또는 Debian 런타임에 복사합니다. 빌드 결과 바이너리가 1 MB 미만이면 빌드가 즉시 실패하는데, 이는 더미/캐시 전용 빌드 아티팩트를 감지하기 위함입니다. 전체 기능 목록은 Cargo 기능 플래그 및 ADR을 참고하세요.

이미지에는 /revka-data/.revka/config.toml에 동작하는 config.toml이 내장되어 있습니다. 일반적으로 API 키만 제공하면 되며, 나머지는 컨테이너에 적합한 기본값을 사용합니다. 환경 변수는 런타임에 내장된 config를 덮어씁니다.

변수기본값의미
API_KEY / REVKA_API_KEY없음LLM 공급자 API 키. 필수 — 런타임에 반드시 제공해야 합니다.
PROVIDERopenrouterLLM 공급자 ID. :latest 이미지는 설정하지 않아 config 파일 편집이 우선합니다. Debian/dev 이미지는 기본값으로 설정합니다.
REVKA_MODEL공급자 기본값모델 재정의(예: anthropic/claude-sonnet-4-20250514).
REVKA_ALLOW_PUBLIC_BINDtrue(Compose/템플릿에서 설정)컨테이너 네트워킹에 필수 — 없으면 게이트웨이가 루프백 외 바인드를 거부합니다.
REVKA_GATEWAY_PORT42617컨테이너 내부 게이트웨이 리슨 포트.
LANGC.UTF-8CJK 및 멀티바이트 입력을 올바르게 처리하기 위한 UTF-8 로케일.
HOME/revka-data홈 디렉터리. config는 /revka-data/.revka/에 위치합니다.
REVKA_WORKSPACE/revka-data/workspace에이전트 워크스페이스 경로.

공급자별 키 변수(OPENROUTER_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY 등)도 사용 가능하며 범용 API_KEY보다 우선합니다. 전체 환경 변수 재정의 목록은 구성 개요를 참고하세요.

저장소에는 프로덕션에 최적화된 docker-compose.yml 참조 파일이 포함되어 있습니다. restart: unless-stopped, 리소스 제한, 명명된 볼륨, 헬스 체크가 구성되어 있습니다. 명령줄이나 .env 파일로 API 키를 제공하세요.

services:
revka:
image: ghcr.io/kumihoio/revka:latest
# For ARM64 where distroless exits immediately, switch to:
# image: ghcr.io/kumihoio/revka:debian
container_name: revka
restart: unless-stopped
environment:
- API_KEY=${API_KEY:-}
- PROVIDER=${PROVIDER:-openrouter}
- REVKA_ALLOW_PUBLIC_BIND=true
- REVKA_GATEWAY_PORT=${REVKA_GATEWAY_PORT:-42617}
volumes:
- revka-data:/revka-data
ports:
- "${HOST_PORT:-42617}:${REVKA_GATEWAY_PORT:-42617}"
deploy:
resources:
limits:
cpus: "2"
memory: 512M
reservations:
cpus: "0.5"
memory: 32M
healthcheck:
test: ["CMD", "revka", "status", "--format=exit-code"]
interval: 60s
timeout: 10s
retries: 3
start_period: 10s
volumes:
revka-data:

라이프사이클 명령어:

Terminal window
# Start in the background (inline key)
API_KEY=sk-or-... docker compose up -d
# Stop and remove the container (the named volume is kept)
docker compose down
# Follow logs
docker compose logs -f revka
# Publish on a different host port (e.g. 42617 is already taken)
HOST_PORT=8080 docker compose up -d

또는 Compose 파일 옆에 .env 파일로 설정을 관리할 수 있습니다.

API_KEY=sk-or-...
PROVIDER=openrouter
HOST_PORT=42617
REVKA_GATEWAY_PORT=42617
변수기본값의미
API_KEY없음공급자 API 키(필수).
PROVIDERopenrouter공급자 ID.
HOST_PORT42617ports 매핑에서 호스트 측 포트.
REVKA_GATEWAY_PORT42617컨테이너 측 게이트웨이 포트.

설정된 리소스 제한은 컨테이너를 최대 2 CPU / 512 MB로 제한하고 0.5 CPU / 32 MB를 예약합니다. Revka의 메모리 사용량은 적으므로 단일 인스턴스에는 충분한 기본값입니다. 다수의 채널이나 대용량 MCP 사이드카를 실행할 경우 제한을 높이세요.

두 Dockerfile과 Compose 파일 모두 동일한 활성 프로브를 사용합니다.

healthcheck:
test: ["CMD", "revka", "status", "--format=exit-code"]
interval: 60s
timeout: 10s
retries: 3
start_period: 10s

revka status --format=exit-code는 표준 컨테이너 활성 확인 방법입니다. 사람이 읽을 수 있는 상태 보고서를 출력하는 대신, 설정된 게이트웨이에 경량 GET /health 요청을 수행하여 게이트웨이가 정상이면 0, **그렇지 않으면 1**을 종료 코드로 반환합니다. 프로브는 바인드 호스트가 [::] 또는 0.0.0.0이면 127.0.0.1로 정규화하고, 설정된 gateway.port를 사용하며, 5초 타임아웃을 적용합니다. start_period는 데몬에 10초의 바인드 대기 시간을 부여하여 재시도 예산에 영향을 주기 전에 초기화를 완료할 수 있도록 합니다.

실행 중인 컨테이너에서 수동으로 실행하려면:

Terminal window
docker exec revka revka status --format=exit-code; echo "exit=$?"

이미지와 Compose 파일은 Podman에서도 동일하게 실행되며, 루트리스 Podman의 사용자 네임스페이스와 SELinux 처리를 위한 두 가지 조정이 필요합니다.

  • --userns keep-id를 추가하여 컨테이너의 UID 65534가 호스트 사용자에게 올바르게 매핑되고 볼륨이 쓰기 가능한 상태를 유지하도록 합니다.
  • 볼륨 마운트에 :Z 접미사를 추가하여 SELinux가 컨테이너용으로 재레이블링하도록 합니다.
Terminal window
podman run -d \
--name revka \
--userns keep-id \
-e API_KEY=sk-or-... \
-e PROVIDER=openrouter \
-v revka-data:/revka-data:Z \
-p 42617:42617 \
ghcr.io/kumihoio/revka:latest

podman compose는 동일한 docker-compose.yml을 읽습니다. 환경 변수, 헬스 체크, 게시된 포트 등 나머지는 Docker와 동일합니다.

Revka에는 세 가지 셀프 호스팅 PaaS 플랫폼을 위한 초안 템플릿이 있습니다. 각 템플릿은 동일한 컨테이너, revka-data 볼륨, 포트 42617, 표준 헬스 체크를 프로비저닝합니다. 차이점은 플랫폼별 이미지 고정 방식과 API 키 시크릿 생성 방식에 있습니다.

Coolify 템플릿(marketplace/coolify/revka.yaml)은 ghcr.io/kumihoio/revka:latest 태그를 대상으로 하는 Compose 서비스입니다. Coolify 사용자는 재배포 시 새 버전을 자동으로 받습니다. Coolify의 ${SERVICE_PASSWORD_APIKEY} 헬퍼를 통해 무작위 API 키가 자동 생성됩니다.

  1. Coolify에서 새 서비스 → Compose를 생성합니다(또는 병합 후 커뮤니티 템플릿 사용).
  2. PROVIDER 환경 변수를 설정하고(기본값 openrouter), 자동 생성된 API_KEY를 수락하거나 직접 입력합니다.
  3. 배포합니다. 포트 42617이 노출되며, 리소스 기본값은 0.5–2 CPU 및 32M–512M 메모리입니다.

Dokploy 블루프린트(marketplace/dokploy/blueprints/revka/)는 고정된 이미지가 필요합니다. Dokploy는 latest 태그를 허용하지 않으므로 ghcr.io/kumihoio/revka:2026.4.21과 같은 CalVer 태그를 참조합니다. 블루프린트에는 도메인과 64자 API 키를 생성하는 docker-compose.ymltemplate.toml이 포함되어 있습니다.

[variables]
main_domain = "${domain}"
api_key = "${password:64}"
[config]
env = [
"API_KEY=${api_key}",
"PROVIDER=openrouter",
"REVKA_ALLOW_PUBLIC_BIND=true",
"REVKA_GATEWAY_PORT=42617"
]
[[config.domains]]
serviceName = "revka"
port = 42617
host = "${main_domain}"
  1. Dokploy에서 Templates를 열고 “Revka”를 검색합니다(리스팅 병합 후 사용 가능).
  2. API_KEY(또는 생성된 키 수락)와 PROVIDER를 설정합니다.
  3. 배포합니다. Dokploy가 생성된 도메인을 포트 42617의 서비스에 할당합니다.

EasyPanel 템플릿(marketplace/easypanel/)도 고정된 이미지가 필요하며 스키마 기반 폼을 제공합니다. meta.yaml에는 네 가지 필드가 정의되어 있습니다.

필드기본값의미
appServiceNamerevkaEasyPanel 내 서비스 이름.
appServiceImageghcr.io/kumihoio/revka:2026.4.21고정된 이미지 태그.
apiKey없음LLM 공급자 API 키.
provideropenrouteropenrouter, openai, anthropic, ollama 중 하나.
  1. EasyPanel에서 **Apps → Browse Templates → “Revka”**로 이동합니다.
  2. API 키를 입력하고 공급자를 선택합니다.
  3. 배포합니다. 배포 후 게이트웨이에 포트 42617로 접근할 수 있습니다.

마켓플레이스 자동 동기화 워크플로

섹션 제목: “마켓플레이스 자동 동기화 워크플로”

GitHub Actions 워크플로(marketplace/sync-marketplace-templates.yml)가 세 플랫폼의 리스팅을 최신 상태로 유지합니다. 각 안정 릴리스 이후 — Docker 이미지가 빌드되어 GHCR에 푸시된 후 실행 — Coolify, Dokploy, EasyPanel 업스트림 저장소에 새 이미지 태그가 포함된 풀 리퀘스트를 엽니다.

  • 입력: release_tag — CalVer 태그(예: 2026.4.21).
  • 시크릿: MARKETPLACE_PAT — 세 업스트림 저장소의 KumihoIO 포크에 푸시하고 PR을 열 수 있는 repo + workflow 스코프의 GitHub 토큰.
  • 트리거: Docker 작업 이후 안정 릴리스 파이프라인에서 자동 실행. 수동 디스패치도 가능합니다.

버전 처리는 플랫폼별로 다릅니다. Coolify:latest를 사용하므로 재배포 시 자동으로 업데이트되어 워크플로가 태그를 변경할 필요가 없습니다. 반면 DokployEasyPanel은 고정 태그가 필요하므로 워크플로가 각 릴리스마다 이미지 태그(및 EasyPanel의 변경 로그)를 재작성합니다. 각 플랫폼의 최초 리스팅은 자동 동기화가 시작되기 전에 수동 PR로 제출해야 합니다.