๐ณ Docker Guide โ OmniRoute (ํ๊ตญ์ด)
๋น ๋ฅธ ์คํ
์น์ ์ ๋ชฉ: โ๋น ๋ฅธ ์คํโ๋ช ๋ น์ด ํ๋๋ก ์ ํ ํธ์คํ ํ์๊ฒ ์ต๋๊น?
์ ํ ํธ์คํ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์ โdocker compose -f docker-compose.selfhost.yml up -d(๊ฒ์๋ ์ด๋ฏธ์ง + Redis, ๋ฃจํ๋ฐฑ ์ ์ฉ, ํ๋กํ ์ ํ ์์). ์๋์ ๋น ๋ฅธ ์คํ์ ์ด๋ฏธ ๋ค๋ฅธ ๊ณณ์์ Redis๋ฅผ ์คํ ์ค์ธ ์ฌ์ฉ์๋ฅผ ์ํ ๋จ์ผ ์ปจํ ์ด๋ ๋ฐฉ์์ ๋๋ค.
docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latestํ๊ฒฝ ํ์ผ ์ฌ์ฉ
์น์ ์ ๋ชฉ: โํ๊ฒฝ ํ์ผ ์ฌ์ฉโ# ๋จผ์ .env๋ฅผ ๋ณต์ฌํ๊ณ ํธ์งํฉ๋๋คcp .env.example .env
docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ --env-file .env \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latestDocker Compose
์น์ ์ ๋ชฉ: โDocker Composeโ# ๊ธฐ๋ณธ ํ๋กํ(CLI ๋๊ตฌ ์์)docker compose --profile base up -d
# CLI ํ๋กํ(Claude Code, Codex, OpenClaw ๋ด์ฅ)docker compose --profile cli up -d
# ํธ์คํธ ํ๋กํ(Linux ์ฐ์ , ํธ์คํธ CLI ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง์ดํธ)docker compose --profile host up -d
# ์น ํ๋กํ(์น ์ธ์
์ ๊ณต์๋ฅผ ์ํ Chromium/Playwright)docker compose --profile web up -d
# CLI + CLIProxyAPI ์ฌ์ด๋์นด ์กฐํฉdocker compose --profile cli --profile cliproxyapi up -d์ฌ์ฉ ๊ฐ๋ฅํ ํ๋กํ
์น์ ์ ๋ชฉ: โ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋กํโOmniRoute๋ ์ฃผ์ ๋ฐฐํฌ ๊ตฌ์ฑ์ ๋ง๋ Compose ํ๋กํ์ ์ ๊ณตํฉ๋๋ค. ํ๊ฒฝ์ ์ ํฉํ ํ๋กํ์ ์ ํํ์ธ์.
| ํ๋กํ | ์๋น์ค | ์ฌ์ฉ ์๊ธฐ | ๋ช ๋ น์ด |
|---|---|---|---|
base (๊ธฐ๋ณธ๊ฐ) |
omniroute-base |
ํค๋๋ฆฌ์ค ์๋ฒ / ์ต์ ๋ฐํ์์ด ํ์ํ๋ฉฐ provider CLI๊ฐ ๋ฒ๋ค๋ก ํฌํจ๋์ง ์์๋ ๋๋ ๊ฒฝ์ฐ | docker compose --profile base up -d |
cli |
omniroute-cli |
omniroute providers/setup/doctor์ ๋ฒ๋ค CLI(Codex, Claude Code, Droid, OpenClaw)๋ฅผ ํธ์ถํ๋ ์์ด์ ํธ ์ํฌํ๋ก |
docker compose --profile cli up -d |
host |
omniroute-host |
~/.local/bin, ~/.codex, ~/.claude ๋ฑ์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง์ดํธํ์ฌ ํธ์คํธ CLI์ network_mode์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ๋ ค๋ Linux ํธ์คํธ |
docker compose --profile host up -d |
cliproxyapi |
cliproxyapi |
์
์คํธ๋ฆผ CLI ํ๋ก์๋ฅผ ์ํด ํฌํธ 8317์์ CLIProxyAPI ์ฌ์ด๋์นด ์คํ |
docker compose --profile cliproxyapi up -d |
web |
omniroute-web |
๋ธ๋ผ์ฐ์ ๊ฐ ํ์ํ ์น ์ธ์
provider: gemini-web, claude-web, claude-turnstile (runner-web ๋น๋, Chromium ํฌํจ) |
docker compose --profile web up -d |
์ฌ๋ฌ ํ๋กํ์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค:
docker compose --profile cli --profile cliproxyapi up -d.
OmniRoute๊ฐ Docker์์ ์คํ๋ ๋ ํธ์คํธ CLI ๋๊ตฌ ๊ตฌ์ฑํ๊ธฐ
์น์ ์ ๋ชฉ: โOmniRoute๊ฐ Docker์์ ์คํ๋ ๋ ํธ์คํธ CLI ๋๊ตฌ ๊ตฌ์ฑํ๊ธฐโomniroute setup-codex, setup-claude, config set <tool> ๋ฐ ๋์๋ณด๋์
๊ตฌ์ฑ ์ ์ฅ ๋ฒํผ์ ๋ชจ๋ ~/.codex/*.config.toml๊ณผ ๊ฐ์ ํ์ผ์ ์์ฑํฉ๋๋ค. ์ด๋ฌํ ๊ฒฝ๋ก๋
CLI๊ฐ ์ค์ ๋ก ์คํ๋๋ ๋จธ์ ์์๋ง ์๋ฏธ๊ฐ ์์ต๋๋ค. ์ปจํ
์ด๋ ๋ด๋ถ์์ ์คํํ๋ฉด
์ปจํ
์ด๋ ์์ฒด์ ํ ๋๋ ํฐ๋ฆฌ(/home/node โ ์ด๋ฏธ์ง๋ USER node๋ก ์คํ๋จ)์ ํ์ผ์ด ์์ฑ๋๋ฏ๋ก,
ํธ์คํธ CLI๊ฐ ์ด๋ฅผ ์ฝ์ ์ ์์ผ๋ฉฐ ์ปจํ
์ด๋๊ฐ ์ฌ์์ฑ๋๋ ์ฆ์ ์ญ์ ๋ฉ๋๋ค.
OmniRoute๋ ์ด๋ฅผ ๊ฐ์งํ์ฌ ์ฌ์ฉํ ์ ์๋ ์ฑ๊ณต ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ๋ ๋์
์๋ด์ ํจ๊ป ์ฐ๊ธฐ๋ฅผ ๊ฑฐ๋ถํฉ๋๋ค. CLI๋ 2๋ก ์ข
๋ฃ๋๊ณ API๋
containerEphemeralTarget: true์ ํจ๊ป 422๋ก ์๋ตํฉ๋๋ค.
๊ถ์ฅ: CLI๋ ํธ์คํธ์์, OmniRoute๋ Docker์์ ์คํ
์น์ ์ ๋ชฉ: โ๊ถ์ฅ: CLI๋ ํธ์คํธ์์, OmniRoute๋ Docker์์ ์คํโ์ปจํ ์ด๋๋ API๋ฅผ ์ ๊ณตํ๊ณ , CLI๋ ํธ์คํธ ๋๊ตฌ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
docker compose --profile base up -d
npm install -g omnirouteomniroute connect http://localhost:20128 # CLI๊ฐ ์ปจํ
์ด๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์ omniroute setup-codex # ํธ์คํธ์ ์ค์ ~/.codex์ ์์ฑ์ด๋ Codex, Claude Code, Cursor ๋๋ ์ ์ฌํ ๋๊ตฌ๋ฅผ ๋ ธํธ๋ถ์์ ์คํํ ๋ ์ ํฉํ ์ ํ์ด๋ฉฐ, ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ค์ ์ ๋๋ค.
๋์: ํธ์คํธ ๊ตฌ์ฑ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ฐ์ธ๋ ๋ง์ดํธ(host ํ๋กํ)
์น์
์ ๋ชฉ: โ๋์: ํธ์คํธ ๊ตฌ์ฑ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ฐ์ธ๋ ๋ง์ดํธ(host ํ๋กํ)โ์ปจํ
์ด๋ ์์ฒด์์ ํธ์คํธ ๊ตฌ์ฑ์ ์์ฑํ๋๋ก ํ๋ ค๋ฉด ํด๋น ๋๋ ํฐ๋ฆฌ๋ฅผ
๋ง์ดํธํ๊ณ CLI_CONFIG_HOME์ด ๋ง์ดํธ ๋ฃจํธ๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์ ํฉ๋๋ค. host ํ๋กํ์๋
์ด๋ฏธ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ๋์ด ์์ต๋๋ค.
environment: - CLI_CONFIG_HOME=/host-home - CLI_ALLOW_CONFIG_WRITES=truevolumes: - ~/.codex:/host-home/.codex:rw - ~/.claude:/host-home/.claude:rw๋ฐ์ธ๋ ๋ง์ดํธ๋ ๊ฒฝ๋ก๋ฅผ ์ ๋ขฐํ ์ ์๊ฒ ํด ์ค๋๋ค. OmniRoute๋
/proc/self/mountinfo๋ฅผ ์ฝ๊ณ ๋ง์ดํธ๋ ๊ฒฝ๋ก๋ฟ ์๋๋ผ ํ์ ํญ๋ชฉ์ด ๋ง์ดํธ๋
๋๋ ํฐ๋ฆฌ(์์ /host-home ๊ตฌ์กฐ๊ฐ ์ ํํ ์ด์ ํด๋นํจ)์ ๋ํ ์ฐ๊ธฐ๋ ํ์ฉํ๋ ํํธ,
๋ง์ดํธ๋์ง ์์ ๊ฒฝ๋ก์ ๋ํ ์ฐ๊ธฐ๋ ๊ณ์ ๊ฑฐ๋ถํฉ๋๋ค.
์์ธ ์ฒ๋ฆฌ: ์ปจํ ์ด๋ ์์ฒด์ CLI ๊ตฌ์ฑ(์ ์คํ๊ฒ ์ฌ์ฉ)
์น์ ์ ๋ชฉ: โ์์ธ ์ฒ๋ฆฌ: ์ปจํ ์ด๋ ์์ฒด์ CLI ๊ตฌ์ฑ(์ ์คํ๊ฒ ์ฌ์ฉ)โCLI๊ฐ ์ค์ ๋ก ์ปจํ
์ด๋ ๋ด๋ถ์ ์๋ ๊ฒฝ์ฐ(cli ํ๋กํ)์๋ ์ฐ๊ธฐ๊ฐ ์๋๋ ๋์์
๋๋ค.
๋ชจ๋ setup-* ๋ช
๋ น์ --allow-container-write๋ฅผ ์ ๋ฌํ๊ฑฐ๋ ์๋ฒ์
OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true๋ฅผ ์ค์ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ํด๋น ์ฐ๊ธฐ ๋ด์ฉ์ด
์ปจํ
์ด๋ ์ข
๋ฃ ํ ์ ์ง๋์ง ์๋๋ค๋ ๊ฒฝ๊ณ ์ ํจ๊ป ์ฐ๊ธฐ๊ฐ ์งํ๋ฉ๋๋ค.
๋ณด์ ๊ฒฝ๊ณ โ
cliํ๋กํ +docker.sock๋ง์ดํธ.cliํ๋กํ์ ์ปจํ ์ด๋ ๋ด ์๋ ์ ๋ฐ์ดํฐ๊ฐ ํธ์คํธ ๋ฐ๋ชฌ์ ํตํด ์คํ์ ์ฌ์์ฑํ ์ ์๋๋ก/var/run/docker.sock์ ๋ฐ์ธ๋ ๋ง์ดํธํฉ๋๋ค. (src/lib/system/autoUpdate.ts๋ ํด๋น ์์ผ์ ํ์งํ๊ณ , ์์ผ์ด ์์ผ๋ฉด Docker ๊ฒฝ๋ก๋ฅผ ๊ฑด๋๋๋๋ค.) ์ด ์์ผ์ ํธ์คํธ root ๊ถํ์ ๋ํ ์ ๋ขฐ ๊ฒฝ๊ณ์ ๋๋ค. ์ด ์์ผ์ ์ ๊ทผํ ์ ์๋ ๋ชจ๋ ๊ฒ์ ํธ์คํธ Docker ๋ฐ๋ชฌ์ root ๊ถํ์ผ๋ก ์ ์ดํ๋ฏ๋ก ํธ์คํธ์ ๋ชจ๋ ์ปจํ ์ด๋๋ฅผ ์์ฑ, ๊ฒ์ฌ, ์ค์ง ๋ฐ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ์ด๋ก ์ธํ ์ฃผ์ ์ฌํญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
cliํ๋กํ์ ํฌํธ๋ฅผ ๋คํธ์ํฌ์ ์ ๋๋ก ๋ ธ์ถํ์ง ๋ง์ธ์.127.0.0.1์ ๊ฒ์ํ์ธ์(ports: "127.0.0.1:${DASHBOARD_PORT:-20128}:..."). LAN์์ ์ ๊ทผ ๊ฐ๋ฅํcliํ๋กํ์ ๋์๋ณด๋ ์์ค์ ๋ชจ๋ RCE๋ฅผ ํธ์คํธ ์ ์ฒด ์นจํด๋ก ํ๋ํฉ๋๋ค.- ์ถ๊ฐ ํธ์คํธ ๋๋ ํฐ๋ฆฌ๋ฅผ
cliํ๋กํ์ ๋ฐ์ธ๋ํ์ง ๋ง์ธ์. Docker ์์ผ๊ณผ ์ถ๊ฐ ๋ง์ดํธ๊ฐ ํจ๊ป ์์ผ๋ฉด ์ปจํ ์ด๋๊ฐ ํ์ผ ์์คํ ๊ณผ ํธ์คํธ ๊ตฌ์ฑ์ ๋ํ ์์ ํ ์ฝ๊ธฐ/์ฐ๊ธฐ ๊ถํ์ ๊ฐ๊ฒ ๋ฉ๋๋ค. ๋๊ตฌ๊ฐ ํ๋ก์ ํธ๋ฅผ ํ์ธํด์ผ ํ๋ค๋ฉด CLI ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฌ์ฉํด ๋ก์ปฌ์์ ์คํํ๊ณ , ํ๋ก์ ํธ๋ฅผcli์ปจํ ์ด๋์ ๋ง์ดํธํ์ง ๋ง์ธ์.์ปจํ ์ด๋ ๋ด๋ถ ์๋ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ์ง ์๋ค๋ฉด
cliํ๋กํ์ ๋นํ์ฑํํ์ธ์ (COMPOSE_PROFILES=core,redis๋๋ ๋ ์งง๊ฒ ์ค์ ). ๋ค๋ฅธ ํ๋กํ์ Docker ์์ผ์ ๋ง์ดํธํ์ง ์์ต๋๋ค.MITM ๊ด๋ จ ์ํ ๋ชจ๋ธ์
docs/security/MITM-TPROXY-DECRYPT.md(git์ ์์ผ๋ฉฐ/docs์๋ ์ปดํ์ผ๋์ง ์์)๋ฅผ,codex/claude-code/droid/openclaw๋ฐ์ด๋๋ฆฌ ์ถ์ฒ ์ฒด์ธ์docs/security/SUPPLY_CHAIN.md๋ฅผ ์ฐธ์กฐํ์ธ์.
Redis ์ฌ์ด๋์นด
์น์ ์ ๋ชฉ: โRedis ์ฌ์ด๋์นดโOmniRoute๋ ๋ถ์ฐ ์๋ ์ ํ๊ธฐ์ ๊ณต์ ์บ์๋ฅผ ์ง์ํ๊ธฐ ์ํด Redis๋ฅผ ์ฌ์ฉํฉ๋๋ค. redis ์๋น์ค๋ docker-compose.yml์ ํญ์ ์ ์๋์ด ์์ผ๋ฉฐ(ํ๋กํ ์ ํ ์์), ๋ค๋ฅธ ์ด๋ค ํ๋กํ๊ณผ๋ ํจ๊ป ์์๋ฉ๋๋ค.
| ์ธ๋ถ ์ ๋ณด | ๊ฐ |
|---|---|
| ์ด๋ฏธ์ง | redis:7-alpine |
| ์ปจํ ์ด๋ ์ด๋ฆ | omniroute-redis |
| ๋ด๋ถ ํฌํธ | 6379 |
| ํธ์คํธ ํฌํธ(์ฌ์ ์) | REDIS_PORT (๊ธฐ๋ณธ๊ฐ: 6379) |
| ํธ์คํธ ๋ฐ์ธ๋ฉ(์ฌ์ ์) | REDIS_BIND_HOST (๊ธฐ๋ณธ๊ฐ: 127.0.0.1) |
| ๋ณผ๋ฅจ | omniroute-redis-data โ /data |
| ์ํ ํ์ธ | redis-cli ping (10์ด ๊ฐ๊ฒฉ) |
๊ด๋ จ ํ๊ฒฝ ๋ณ์:
REDIS_URLโ ์ฑ์ ์ฃผ์ ๋๋ ์ฐ๊ฒฐ ๋ฌธ์์ด(๊ธฐ๋ณธ๊ฐ:redis://redis:6379).REDIS_PORTโ Redis ์ปจํ ์ด๋์ ํธ์คํธ ์ธก ํฌํธ ๋งคํ.REDIS_BIND_HOSTโ ํฌํธ๊ฐ ๊ฒ์๋๋ ํธ์คํธ ์ธํฐํ์ด์ค. ๊ธฐ๋ณธ๊ฐ์127.0.0.1์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ฃจํ๋ฐฑ์ ์ฌ์ฉํ๋ ์ด์ : ์ฌ์ด๋์นด๋
requirepass์์ด ์คํ๋๋ฉฐ, ์ฑ ์ปจํ ์ด๋๋ compose ๋คํธ์ํฌ(redis:6379)๋ฅผ ํตํด ์ฌ์ด๋์นด์ ์ฐ๊ฒฐํฉ๋๋ค. ๊ฒ์๋ ํฌํธ๋ ํธ์คํธ ์ธก ๋๊ตฌ(redis-cli, ๋ก์ปฌnpm run dev)์์๋ง ์ฌ์ฉ๋ฉ๋๋ค.0.0.0.0์ ๊ฒ์ํ๋ฉด ์ธ์ฆ๋์ง ์์ Redis๊ฐ LAN์ ๋ชจ๋ ํธ์คํธ์ ๋ ธ์ถ๋ฉ๋๋ค.REDIS_BIND_HOST=0.0.0.0์ผ๋ก ์ค์ ํ๋ ๊ฒฝ์ฐ ์๋น์ค์command:์๋--requirepass๋ฅผ ์ถ๊ฐํ์ธ์.
Redis ๋นํ์ฑํ๋ ๊ถ์ฅํ์ง ์์ต๋๋ค(์๋ ์ ํ๊ธฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋ด ํด๋ฐฑ์ผ๋ก ์ฑ๋ฅ ์ ํ๋จ). ๋ฐ๋์ ๋นํ์ฑํํด์ผ ํ๋ค๋ฉด docker-compose.yml์์ redis: ์๋น์ค ๋ธ๋ก์ ์ ๊ฑฐํ๊ฑฐ๋ ์ฃผ์ ์ฒ๋ฆฌํ๊ฑฐ๋, ๋ค์๊ณผ ๊ฐ์ด ์ธ์คํด์ค ์๋ฅผ 0์ผ๋ก ์กฐ์ ํ์ธ์.
docker compose up -d --scale redis=0ํ๋ก๋์ Compose
์น์ ์ ๋ชฉ: โํ๋ก๋์ Composeโ๊ฐ๋ฐ ํ๊ฒฝ๊ณผ ํจ๊ป ์คํ๋๋ ๊ฒฉ๋ฆฌ๋ ํ๋ก๋์
์ค๋
์ท์๋ docker-compose.prod.yml์ ์ฌ์ฉํ์ธ์.
| ์ธ๋ถ ์ ๋ณด | ๊ฐ |
|---|---|
| ํ์ผ | docker-compose.prod.yml |
| ๊ธฐ๋ณธ ๋์๋ณด๋ ํฌํธ | PROD_DASHBOARD_PORT=20130 (๋ด๋ถ ${DASHBOARD_PORT:-20128}์ ๋งคํ) |
| ๊ธฐ๋ณธ API ํฌํธ | PROD_API_PORT=20131 |
| ์ด๋ฏธ์ง | omniroute:prod (runner-cli ๋์์์ ๋น๋) |
| Redis ์ปจํ ์ด๋ | omniroute-redis-prod (redis:8.6.2, ์ ์ฉ redis-prod-data ๋ณผ๋ฅจ) |
| ๋ฐ์ดํฐ ๋ณผ๋ฅจ | omniroute-prod-data (๋ช
๋ช
๋ ๋ณผ๋ฅจ, ์ฌ๋น๋ ํ์๋ ์ ์ง๋จ) |
| ์ํ ํ์ธ | node healthcheck.mjs + redis-cli ping, Redis ์ํ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ํ๋ depends_on |
์ฌ์ฉ ๋ฐฉ๋ฒ:
# ํ๋ก๋์
์คํ ๋น๋ ๋ฐ ์์docker compose -f docker-compose.prod.yml up -d --build
# ๋ก๊ทธ ์คํธ๋ฆฌ๋ฐdocker compose -f docker-compose.prod.yml logs -f
# ์ข
๋ฃ(๋ณผ๋ฅจ ์ ์ง)docker compose -f docker-compose.prod.yml downํ๋ก๋์ ์คํ์ ๊ฐ๋ฐ์ฉ compose์ ์๋ก ๋ค๋ฅธ ์ปจํ ์ด๋ ์ด๋ฆ, ํฌํธ ๋ฐ ๋ณผ๋ฅจ์ ์ฌ์ฉํ์ฌ ๋ณ๋ ฌ๋ก ์คํ๋๋ฏ๋ก, ํ๋ก๋์ ์ ๊ณ์ ์คํํ๋ฉด์ ๋ก์ปฌ์์ ๊ฐ๋ฐ์ ์ด์ด๊ฐ ์ ์์ต๋๋ค.
Dockerfile ์คํ ์ด์ง
์น์ ์ ๋ชฉ: โDockerfile ์คํ ์ด์งโ์ด ์ ์ฅ์๋ ๋ฉํฐ ์คํ
์ด์ง Dockerfile(Dockerfile)์ ์ ๊ณตํฉ๋๋ค. ๋ค ๊ฐ์ ์คํ
์ด์ง๊ฐ ๊ณต๊ฐ๋์ด ์์ผ๋ฏ๋ก ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋ target์ ์ ํํ์ธ์.
| ์คํ ์ด์ง | ๋ฒ ์ด์ค ์ด๋ฏธ์ง | ์ฉ๋ |
|---|---|---|
builder |
node:26-trixie-slim |
์ข
์์ฑ์ ์ค์นํ๊ณ (npm ci --legacy-peer-deps) npm run build๋ฅผ ์คํํฉ๋๋ค(๊ธฐ๋ณธ๊ฐ์ Turbopack โ ์๋์ ๋น๋ ์ ๋ฆฌ์์ค ์ฐธ์กฐ). |
runner-base |
node:26-trixie-slim |
Next.js ๋ ๋ฆฝ ์คํํ ์ถ๋ ฅ์ด ํฌํจ๋ ํ๋ก๋์ ๋ฐํ์์ ๋๋ค. ํ๋ก๋ฐ์ด๋ CLI๋ ํฌํจ๋์ง ์์ต๋๋ค. |
runner-cli |
runner-base |
git, docker.io, docker-compose ๋ฐ ์ ์ญ CLI์ธ @openai/codex, @anthropic-ai/claude-code, droid, openclaw๋ฅผ ์ถ๊ฐํฉ๋๋ค. ์์ด์ ํธํ ์ํฌํ๋ก์๋ ์ด๊ฒ์ ์ ํํ์ธ์. |
runner-web |
runner-base |
์น ์ธ์
ํ๋ก๋ฐ์ด๋์ธ gemini-web, claude-web, claude-turnstile์ ์ํด Playwright์ Chromium ๋ธ๋ผ์ฐ์ (--with-deps)๋ฅผ ์ถ๊ฐํฉ๋๋ค. ์ด๋ฌํ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฌ์ฉํ ๋ ์ ํํ์ธ์ โ ์ผ๋ฐ ์ด๋ฏธ์ง๋ ์ด๊ฒ์ด ์์ผ๋ฉด ์์ฒญ ์ ์คํจํฉ๋๋ค(๋ฆด๋ฆฌ์ค ์ฑ๋ ์๋์ -web ์ฐธ๊ณ ์ฌํญ ์ฐธ์กฐ). |
ํน์ ๋์์ ์๋์ผ๋ก ๋น๋ํ๋ ค๋ฉด ๋ค์์ ์คํํ์ธ์.
docker build --target runner-base -t omniroute:base .docker build --target runner-cli -t omniroute:cli .docker build --target runner-web -t omniroute:web .๋น๋ ์ ๋ฆฌ์์ค
์น์ ์ ๋ชฉ: โ๋น๋ ์ ๋ฆฌ์์คโ์ธ ๊ฐ์ง ๋น๋ ์ธ์๊ฐ builder ์คํ
์ด์ง์ ๋ฆฌ์์ค ์ฌ์ฉ๋์ ์ ์ดํฉ๋๋ค. ์ด ์ธ์๋ค์ ๋น๋ ์์๋ง ์ ์ฉ๋๋ฉฐ โ
OMNIROUTE_MEMORY_MB(์๋ ์ฐธ์กฐ)๋ ๋ณ๋์ ๋ฐํ์ ์กฐ์ ์ต์
์
๋๋ค.
| ๋น๋ ์ธ์ | ๊ธฐ๋ณธ๊ฐ | ํจ๊ณผ |
|---|---|---|
OMNIROUTE_USE_TURBOPACK |
1 |
0์ด๋ฉด ๋์ webpack์ผ๋ก ๋น๋ํฉ๋๋ค. ์ต๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ง๋ง ๋ ๋๋ฆฝ๋๋ค. |
OMNIROUTE_BUILD_MEMORY_MB |
6144 |
์์ฑ๋ next build์ V8 ํ ์ํ(--max-old-space-size)์
๋๋ค. |
OMNIROUTE_BUILD_WORKERS |
2 |
CIRCLE_NODE_TOTAL์ ์ ๋ฌ๋๋ฉฐ, Next๋ ํ์ด์ง ๋ฐ์ดํฐ ์์ง์ ์ฌ์ฉํ workers = N - 1์ ๋์ถํฉ๋๋ค. |
OMNIROUTE_BUILD_WORKERS๋ ๋๊ท๋ชจ ๋น๋์์ ๋๋ ค์ผ ํ๋ ๊ฐ์ด๋ฉฐ, ๋ฆฌ์์ค๊ฐ ์ ํ๋ ๋น๋๊ฐ
โ Compiled successfully ์ดํ์ ์ข
๋ฃ๋ ๋ ์์ฌํด์ผ ํ๋ ๊ฐ์
๋๋ค. ๊ฐ
ํ์ด์ง ๋ฐ์ดํฐ ์์ปค๋ ์์ฒด ํ๋ก์ธ์ค์ด๋ฉฐ, ์์ next build ์์ฒด๋ ๋ณ๋์ ํ๋ก์ธ์ค์
๋๋ค.
์ค์ VPS ์ฌํ(issue #7518)์์ ๊ฐ ํ๋ก์ธ์ค์ ์ต๋ RSS๊ฐ
NODE_OPTIONS ํ ํ๋๊ทธ์ ๋ฌด๊ดํ๊ฒ ์ฝ 4.5 GB๋ก ์ธก์ ๋์์ต๋๋ค(Turbopack์
V8 ํ ์ธ๋ถ์ ๋ค์ดํฐ๋ธ/Rust ๋ฉ๋ชจ๋ฆฌ์์ ์ปดํ์ผํฉ๋๋ค). ๊ธฐ๋ณธ๊ฐ 2(โ ์์ปค 1๊ฐ, ์ด
ํ๋ก์ธ์ค 2๊ฐ)๋ ๊ฒ์ ํ์ดํ๋ผ์ธ์์ ์ฌ์ฉํ๋ 16 GB / 4 vCPU GitHub ํธ์คํ
๋ฌ๋์
๋ง์ถฐ ์ค์ ๋์์ต๋๋ค. 8(โ ์์ปค 7๊ฐ)์์๋ ํด๋น ๋ฌ๋์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํด์ก๊ณ
buildkit์ด ResourceExhausted: ... cannot allocate memory์ ํจ๊ป ๋จ๊ณ๋ฅผ ์คํจ ์ฒ๋ฆฌํ์ต๋๋ค.
ํ๋ก์ธ์ค๋ณ RSS๋ฅผ ์ถ๋ก ํ์ง ์๊ณ ์ง์ ์ธก์ ํ ๊ฒฐ๊ณผ, 3(โ ์์ปค 2๊ฐ)๋ ์ฌ์ ํ
๋ฉ๋ชจ๋ฆฌ์ ๋ง์ง ์์์ต๋๋ค. tests/unit/docker-build-memory-budget.test.ts๋
์ธก์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ๊ณ์ฐํ๋ฉฐ, ์ด๋ ์กฐ์ ๊ฐ์ด๋ ๋ฌ๋์ ์ฉ๋์ ์ด๊ณผํ๋ฉด ์คํจํฉ๋๋ค.
Turbopack์ V8 ํ ์ธ๋ถ์ ์กด์ฌํ๋ ๋ค์ดํฐ๋ธ Rust ๋ฉ๋ชจ๋ฆฌ์์ ์ปดํ์ผํ๋ฏ๋ก
OMNIROUTE_BUILD_MEMORY_MB๋ก ์ด๋ฅผ ์ ํํ ์ ์์ต๋๋ค. ๋ฉ๋ชจ๋ฆฌ ์ํ์ด ์๋ ํธ์คํธ์์๋
์ค๋ฅ ํ
์คํธ๊ฐ ์ ํ ํ์๋์ง ์์ ์ฑ OOM ํฌ๋ฌ์ ์ํด ๋น๋๊ฐ SIGKILL๋ฉ๋๋ค. ์ฆ,
Creating an optimized production build ๋์ค์ ๋จ์ํ ์ค์ง๋๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ์ด
์๋๋ผ ๋ฉ์ถ ๊ฒ์ฒ๋ผ ๋ณด์
๋๋ค. ๋น๋ ํธ์คํธ์ ๋ฆฌ์์ค๊ฐ ์ ํ๋ ๊ฒฝ์ฐ ๋ฒ๋ค๋ฌ๋ฅผ ์ ํํ์ธ์.
docker build --target runner-base \ --build-arg OMNIROUTE_USE_TURBOPACK=0 \ -t omniroute:base .webpackBuildWorker๊ฐ ํ์ฑํ๋์ด ์์ผ๋ฏ๋ก next build๋ ์์ ํ๋ก์ธ์ค์ ๋ณ๋์ ์์ปค
ํ๋ก์ธ์ค๋ฅผ ์คํํ๋ฉฐ, ๊ฐ ํ๋ก์ธ์ค๋ OMNIROUTE_BUILD_MEMORY_MB๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ์ค์ํฉ๋๋ค.
์ปจํ
์ด๋ ์ํ์ ํด๋น ๊ฐ์ ํ ๋ฐฐ๊ฐ ์๋๋ผ ๋๋ต ๋ ๋ฐฐ๋ณด๋ค ๋๊ฒ ์ค์ ํ์ธ์.
์ด ํธ๋ฆฌ์์ ์ธก์ ํ ๊ฒฐ๊ณผ(--target runner-base, OMNIROUTE_BUILD_MEMORY_MB=6144):
| ๋ฒ๋ค๋ฌ | ์ปจํ ์ด๋ ์ํ | ๊ฒฐ๊ณผ |
|---|---|---|
| Turbopack | 8 GiB / 16 GiB | ๋ ๊ฒฝ์ฐ ๋ชจ๋ ์กฐ์ฉํ OOM ์ข ๋ฃ๋จ |
| webpack | 8 GiB | ๋น๋ ์์ปค๊ฐ SIGKILL๋จ |
| webpack | 12 GiB | ์ฑ๊ณต, ์ต๋ 11.1 GiB ์ฌ์ฉ |
๋ฐํ์ ๊ธฐ๋ณธ๊ฐ
์น์ ์ ๋ชฉ: โ๋ฐํ์ ๊ธฐ๋ณธ๊ฐโrunner-base์์ ๋ด๋ณด๋ด๋ ๊ธฐ๋ณธ๊ฐ: PORT=20128, HOSTNAME=0.0.0.0, OMNIROUTE_MEMORY_MB=1024, NODE_OPTIONS=--max-old-space-size=1024, DATA_DIR=/app/data, OMNIROUTE_MIGRATIONS_DIR=/app/migrations.
Docker์์์ ๋ฉ๋ชจ๋ฆฌ ๋์:
- ์ด๋ฏธ์ง๋
OMNIROUTE_MEMORY_MB=1024๋ฅผ ์ค์ ํ๊ณ , ์ฌ๊ธฐ์์NODE_OPTIONS=--max-old-space-size=1024๋ฅผ ํ์ํฉ๋๋ค. - ์ค์ ์๋ฒ ํ๋ก์ธ์ค๋ ๋
๋ฆฝ ์คํํ ๋ฐ์ฒ์ ์ํด ์์๋๋ฉฐ, ๋ฐ์ฒ๋
OMNIROUTE_MEMORY_MB๋ฅผ ์ฝ๊ณ--max-old-space-size=<OMNIROUTE_MEMORY_MB>๋ฅผ ์ถ๊ฐํฉ๋๋ค. - Node๋ ๋ฐ๋ณต๋
--max-old-space-size๊ฐ ์ค ๋ง์ง๋ง ๊ฐ์ ์ฌ์ฉํ๋ฏ๋ก,OMNIROUTE_MEMORY_MB๋ฅผ ์ค์ ํ๋ฉด ์ค์ง์ ์ธ Docker ํ ์ ํ์ ์ ์ดํ ์ ์์ต๋๋ค. - ์ด๋ฏธ์ง์์ ์ด ๊ฐ์ ํญ์ ์ค์ ํ๋ฏ๋ก Docker์์๋ ๋ฐ์ฒ ์์ฒด์ RAM ๊ธฐ๋ฐ ๋ณด์ ํด๋ฐฑ์ด ์ ์ฉ๋์ง ์์ต๋๋ค. ์ํฌ๋ก๋์ ๋ง๊ฒ ๋ช
์์ ์ผ๋ก ๋๋ฆฌ์ญ์์ค(์๋ ํ ์ฐธ์กฐ). ์ฝ๋ฉ ์์ด์ ํธ์
/v1/responses์๋2048๋ ์ฌ์ ํ ๋๋ฌด ์์ต๋๋ค.
์ฝ๋ฉ ์์ด์ ํธ์ ๋ฐํ์ RAM
์น์ ์ ๋ชฉ: โ์ฝ๋ฉ ์์ด์ ํธ์ ๋ฐํ์ RAMโDocker ๊ธฐ๋ณธ๊ฐ์ธ 1โฏGiB๋ ๋์๋ณด๋/๊ฐ๋ฒผ์ด ์ฑํ
์ ์ํ ์ต์ ๊ธฐ์ค์ด์ง, ํ๋ก๋์
ํ๊ฒฝ์ ์ ํฉํ ํฌ๊ธฐ๊ฐ ์๋๋๋ค. ๊ธด POST /v1/responses ๋ณธ๋ฌธ(์๋ฐฑ ๊ฐ์ ๋ฉ์์ง์ ์์ญ ๊ฐ์ ๋๊ตฌ)์ ์์ถ ์ค์ ์ฌ๋ฌ ์ธ๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ํ๋ฅผ ์ ์งํฉ๋๋ค. ์๋ก ๊ฒน์ณ ์คํ๋ ์ฝ 3โฏMiB / ์ฝ 750k ํ ํฐ ์์ฒญ ๋ ๊ฑด์ 12โฏGiB old-space์์ V8์ ์ค๋จ์์ผฐ์ผ๋ฉฐ(FATAL ERROR: Reached heap limit), 16โฏGiB cgroup OOM๋ ๋ฐ์์์ผฐ์ต๋๋ค. #7849๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
cgroup --memory๋ ํ๋ณด๋ค ํฌ๊ฒ ์ค์ ํ์ญ์์ค โ ๋ค์ดํฐ๋ธ ๋ฒํผ, SQLite ๋ฐ ์์ถ ์ค๊ฐ ๋ฐ์ดํฐ๋ V8 ์ธ๋ถ์ ์์นํฉ๋๋ค.
| ์ํฌ๋ก๋ | OMNIROUTE_MEMORY_MB |
์ปจํ ์ด๋ / cgroup | ์ฐธ๊ณ |
|---|---|---|---|
| ๋์๋ณด๋, ๊ฐ๋ฒผ์ด ์ฑํ ํ๋ | 1024 (์ด๋ฏธ์ง ๊ธฐ๋ณธ๊ฐ) |
โฅ2โฏGiB | |
| ์ฝ๋ฉ ์์ด์ ํธ ํ๋(Claude/Codex/Grok) | 8192 |
โฅ10โฏGiB | ์ผ๋ฐ์ ์ธ ๋จ์ผ ์ธ์
/v1/responses |
๋์์ ์คํ๋๋ ๊ธด /v1/responses ๋ ๊ฑด |
10240โ12288 |
โฅ12โ16โฏGiB | ์ฝ 12โฏGiB ํ์์ V8 ์ค๋จ์ด ์ธก์ ๋จ |
| ๋์์ ์คํ๋๋ ๊ธด ์ปจํ ์คํธ ์ธ ๊ฐ ์ด์ | ๋จ์ผ ํ๋ก์ธ์ค์์ ์คํํ์ง ๋ง ๊ฒ | ์ง๋ ฌํ / RAM ์ฆ์ค | ๊ธฐ๋ณธ ๊ณ ๋ถํ ์์ ํ์ฉ๋์ ์คํ ์ค 1๊ฑด์ด๋ฉฐ, RAM์ ๋๋ฆฌ์ง ์๊ณ ์ด ๊ฐ์ ๋์ด๋ฉด ์ค๋จ์ด ๋ค์ ๋ฐ์ํจ |
๋ฒ ์ด ๋ฉํ์์ omniroute serve๋ OMNIROUTE_MEMORY_MB๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ RAM์ ์ฝ 35%๋ก ๋ณด์ ํฉ๋๋ค([512, 4096] ๋ฒ์๋ก ์ ํ). Docker๋ ํญ์ 1024๋ฅผ ์ค์ ํ๋ฏ๋ก ๊ณต์ ์ด๋ฏธ์ง์์๋ ์ด ๋ณด์ ์ด ์คํ๋์ง ์์ต๋๋ค.
docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \ -e OMNIROUTE_MEMORY_MB=8192 --memory=10g \ -p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest์ค์ํ ํ๊ฒฝ ๋ณ์
์น์ ์ ๋ชฉ: โ์ค์ํ ํ๊ฒฝ ๋ณ์โENVIRONMENT.md์ ๋ฌธ์ํ๋ ๊ธฐ๋ณธ๊ฐ ์ธ์๋ Docker์์ ์คํํ ๋๋ ๋ค์ ๋ณ์๊ฐ ๊ฐ์ฅ ์ค์ํฉ๋๋ค.
| ๋ณ์ | ์ฉ๋ | ๊ธฐ๋ณธ๊ฐ |
|---|---|---|
OMNIROUTE_WS_BRIDGE_SECRET |
WebSocket ๋ธ๋ฆฌ์ง์ ๊ณต์ ๋น๋ฐ ๊ฐ์ ๋๋ค. ํ๋ก๋์ ํ๊ฒฝ์์๋ ํ์์ด๋ฉฐ, ๊ฐ๋ ฅํ ๋ฌด์์ ๋ฌธ์์ด๋ก ์ค์ ํ์ธ์. | ์ค์ ๋์ง ์์(์ ๊ณต ํ์) |
REDIS_URL |
์๋ ์ ํ๊ธฐ/์บ์ ๋ฐฑ์๋์ ์ฐ๊ฒฐ ๋ฌธ์์ด | redis://redis:6379 |
REDIS_PORT |
๋ฒ๋ค Redis ์ปจํ ์ด๋์ ํธ์คํธ ์ธก ํฌํธ | 6379 |
REDIS_BIND_HOST |
๋ฒ๋ค Redis ํฌํธ๊ฐ ๊ฒ์๋๋ ํธ์คํธ ์ธํฐํ์ด์ค(AUTH๋ฅผ ์ถ๊ฐํ์ง ์๋ ํ ๋ฃจํ๋ฐฑ) | 127.0.0.1 |
AUTO_UPDATE_HOST_REPO_DIR |
์์ฒด ์
๋ฐ์ดํธ ์ํฌํ๋ก๋ฅผ ์ํด cli ํ๋กํ์์ /workspace/omniroute์ ๋ง์ดํธ๋๋ ํธ์คํธ ๊ฒฝ๋ก |
. (ํ์ฌ ๋๋ ํฐ๋ฆฌ) |
OMNIROUTE_MEMORY_MB |
Docker ๋
๋ฆฝ ์คํํ ์๋ฒ์ ๋ฐํ์ Node ํ ์ํ์ด๋ฉฐ, ์์ ์ด๋ฏธ์ง ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ ์ํฉ๋๋ค. ์ฝ๋ฉ ์์ด์ ํธ: 8192 ์ด์(๋ฐํ์ RAM ์ฐธ์กฐ). |
1024 |
DASHBOARD_PORT / API_PORT |
๋์๋ณด๋(20128) ๋ฐ API(20129)์ ๋ ธ์ถ ํฌํธ๋ฅผ ์ฌ์ ์ํฉ๋๋ค. | 20128 / 20129 |
APP_BIND_HOST |
docker-compose๊ฐ ๋์๋ณด๋/API/๋ผ์ด๋ธ WS ํฌํธ๋ฅผ ๊ฒ์ํ๋ ํธ์คํธ ์ธํฐํ์ด์ค์
๋๋ค. REQUIRE_API_KEY=false(๊ธฐ๋ณธ๊ฐ)์ด๋ฉด 0.0.0.0์ ์ต๋ช
/v1 ํ๋ก์๋ฅผ LAN์ ๋
ธ์ถํ๋ฏ๋ก, REQUIRE_API_KEY=true๋ก ์ค์ ํ๊ฑฐ๋ ์๋จ์ ๋ฆฌ๋ฒ์ค ํ๋ก์๋ฅผ ๋ ๊ฒฝ์ฐ์๋ง ๋ฒ์๋ฅผ ํ์ฅํ์ธ์. |
127.0.0.1 |
CLIPROXY_BIND_HOST |
docker-compose๊ฐ cliproxyapi ์ฌ์ด๋์นด๋ฅผ ๊ฒ์ํ๋ ํธ์คํธ ์ธํฐํ์ด์ค์ด๋ฉฐ, ํด๋น ๋ฐ์ดํฐ ๋ณผ๋ฅจ์๋ ๊ณต๊ธ์ ์๊ฒฉ ์ฆ๋ช
์ด ์ ์ฅ๋ฉ๋๋ค. |
127.0.0.1 |
OMNIROUTE_PLUGINS_DIR |
๋ฐํ์ ํ๋ฌ๊ทธ์ธ ์ค์บ๋๊ฐ ์ฝ๊ณ ์ค์นํ๋ ๋๋ ํฐ๋ฆฌ์
๋๋ค. ํ๋ฌ๊ทธ์ธ์ด ๋ฐ์ธ๋ ๋ง์ดํธ๋ ๊ฒฝ์ฐ ์ค์ ํ์ธ์. ๊ธฐ๋ณธ๊ฐ์ HOME์ ๋ฐ๋ฅด์ง๋ง ์ด๋ฏธ์ง์์ ์ด๋ฅผ ๋ด๋ณด๋ด์ง ์์ ์๋ ์์ต๋๋ค. |
~/.omniroute/plugins |
OMNIROUTE_BASE_PATH |
์ฑ์ด ๋ฆฌ๋ฒ์ค ํ๋ก์ ๋ค์ ๊ฒ์๋ ๋ ์ฌ์ฉํ๋ URL ํ์ ๊ฒฝ๋ก(์: /omniroute) |
(๋น์ด ์์ = ๋ฃจํธ) |
NEXT_PUBLIC_BASE_URL |
ํ์ ๊ฒฝ๋ก๋ฅผ ํฌํจํ ๊ณต๊ฐ ๋ธ๋ผ์ฐ์ ์๋ณธ ์ฃผ์(์: https://host/omniroute) |
์ค์ ๋์ง ์์ |
PROD_DASHBOARD_PORT |
docker-compose.prod.yml์ ํธ์คํธ ์ธก ๋์๋ณด๋ ํฌํธ |
20130 |
CLIPROXYAPI_PORT |
cliproxyapi ์ฌ์ด๋์นด์ ํธ์คํธ ์ธก ํฌํธ |
8317 |
ํ์ ๊ฒฝ๋ก์ ๋ฆฌ๋ฒ์ค ํ๋ก์ (Traefik / nginx)
์น์ ์ ๋ชฉ: โํ์ ๊ฒฝ๋ก์ ๋ฆฌ๋ฒ์ค ํ๋ก์ (Traefik / nginx)โNext.js basePath๋ standalone ๋ฒ๋ค์ ์ปดํ์ผ๋ฉ๋๋ค. OmniRoute๋ ์ฑ ๋ฃจํธ์ ์ผํฐ๋ ํ์ผ์ ๋น๋ ์ ์ ์ฉ๋ ๊ฐ์ ๊ธฐ๋กํ๊ณ (npm run build ์คํ ์ค ์์ฑ๋๋ฉฐ scripts/docker/ensure-docker-base-path.mjs์์ ์ฝ์), ์ปจํ
์ด๋๊ฐ ์์๋ ๋ ํด๋น ๊ฐ์ OMNIROUTE_BASE_PATH์ ๋น๊ตํฉ๋๋ค. ๊ฐ์ด ์๋ก ๋ค๋ฅด๊ณ ์ด๋ฏธ์ง๊ฐ ๋๋ฉ์ธ ๋ฃจํธ์ฉ์ผ๋ก ๋น๋๋ ๊ฒฝ์ฐ, ์ํธ๋ฆฌํฌ์ธํธ๋ node dev/run-standalone.mjs๊ฐ ์คํ๋๊ธฐ ์ ์ standalone ๋งค๋ํ์คํธ, ํฌํจ๋ basePath/assetPrefix ๋ฆฌํฐ๋ด(Next 16์ assetPrefix๋ง ์ฌ์ฉํ์ฌ SSR ์ ์
URL์ ๋ ๋๋งํ๋ฏ๋ก ํจ์ฒ๊ฐ ํ์ ๊ฒฝ๋ก๋ฅผ ํด๋น ๊ฐ์๋ ๋ฐ์ํจ), ๋น๋ ์ ํฌํจ๋ /_next/static ์ ์
URL(ํด๋ผ์ด์ธํธ ์ฐธ์กฐ ๋งค๋ํ์คํธ, ๋ฏธ๋์ด ๊ฐ์ ธ์ค๊ธฐ, ์ฌ์ ๋ ๋๋ง๋ ์ค๋ฅ ํ์ด์ง) ๋ฐ ํด๋ผ์ด์ธํธ process.env ์ฌ์ ๋ค์ ์์ฑํฉ๋๋ค.
Compose ๋น๋(๊ถ์ฅ)
์น์ ์ ๋ชฉ: โCompose ๋น๋(๊ถ์ฅ)โ์ด๋ฏธ์ง์ ๋ฐํ์์ ์ค์ ์ด ์ผ์นํ๋๋ก .env์ ๋ ๋ณ์๋ฅผ ๋ชจ๋ ์ค์ ํ ํ ๋ค์ ๋น๋ํฉ๋๋ค.
OMNIROUTE_BASE_PATH=/omnirouteNEXT_PUBLIC_BASE_URL=https://myhostname.example.com/omniroutedocker compose --profile base up -d --builddocker-compose.yml์ OMNIROUTE_BASE_PATH๋ฅผ Docker ๋น๋ ์ธ์์ ๋ฐํ์ ํ๊ฒฝ ๋ณ์๋ก ์ ๋ฌํฉ๋๋ค.
์ฌ์ ๋น๋๋ ๋ฃจํธ ์ด๋ฏธ์ง + ๋ฐํ์ ํ์ ๊ฒฝ๋ก
์น์ ์ ๋ชฉ: โ์ฌ์ ๋น๋๋ ๋ฃจํธ ์ด๋ฏธ์ง + ๋ฐํ์ ํ์ ๊ฒฝ๋กโ๊ฒ์๋ diegosouzapw/omniroute:* ์ด๋ฏธ์ง๋ ๋๋ฉ์ธ ๋ฃจํธ์ฉ์ผ๋ก ๋น๋๋ฉ๋๋ค. ๋ฐํ์์ OMNIROUTE_BASE_PATH๋ฅผ ์ค์ ํ ์๋ ์์ผ๋ฉฐ, ์ปจํ
์ด๋๋ ์์ ์ ๋ฒ๋ค์ ํ ๋ฒ ํจ์นํฉ๋๋ค. ์ด์ ๋์ํ๋ ๊ณต๊ฐ ์ค๋ฆฌ์ง๋ ํจ๊ป ์ค์ ํ์ญ์์ค.
services: omniroute: image: diegosouzapw/omniroute:latest environment: OMNIROUTE_BASE_PATH: /omniroute NEXT_PUBLIC_BASE_URL: https://myhostname.example.com/omniroute๋ฆฌ๋ฒ์ค ํ๋ก์๊ฐ ์ธ๋ถ ๊ฒฝ๋ก ์ ์ฒด๋ฅผ ์ ๋ฌํ๋๋ก ์ค์ ํ์ญ์์ค(์ ๋์ฌ๋ฅผ ์ ๊ฑฐํ์ง ๋ง์ญ์์ค). Traefik์ StripPrefix ์์ด PathPrefix(/omniroute)๋ฅผ ์ปจํ
์ด๋๋ก ๋ผ์ฐํ
ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด Next.js๊ฐ /omniroute/...๋ฅผ ์์ ํ๊ณ /omniroute/_next/...์์ ์ ์
์ ์ ๊ณตํฉ๋๋ค.
Docker ํฌ์ค ์ฒดํฌ๋ ํ์ฑ OMNIROUTE_BASE_PATH๊ฐ ์ ๋์ฌ๋ก ์ถ๊ฐ๋ ๊ฒฝ๋ /healthz ์๋ช
์ฃผ๊ธฐ ์๋ํฌ์ธํธ๋ฅผ ๊ฒ์ฌํฉ๋๋ค. /api/monitoring/health๋ ์ฌ์ฉ์/๋์๋ณด๋ ์ง๋จ์ฉ์ผ๋ก ๊ณ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ปจํ
์ด๋ HEALTHCHECK๊ฐ ์ด ์๋ํฌ์ธํธ๋ฅผ ๋ค์ ์ฌ์ฉํ๋๋ก ํ๋ ค๋ฉด(์: ์ฌ์ธต ์ํ ๊ฒ์ฌ๋ฅผ ๊ฐ์ ํ๋ ค๋ ๊ฒฝ์ฐ) OMNIROUTE_HEALTHCHECK_PATH=/api/monitoring/health๋ฅผ ์ค์ ํ์ญ์์ค. ์ด ๊ฒฝ๋ก๋ ์ฌ์ธต ๊ฒ์ฌ(DB + ๋ชจ๋ํฐ๋ง ์์ฝ)์
๋๋ค. ๋ค์ ์ฌ์ฉํ๋๋ก ์ค์ ํ ๊ฒฝ์ฐ Docker์ ๋ฎ์ ๋น๋๋ก ์คํ๋๋ HEALTHCHECK์๋ ์ ํฉํ์ง๋ง, Kubernetes livenessProbe ์ฃผ๊ธฐ์๋ ์ ํฉํ์ง ์์ต๋๋ค.
์ค์ผ์คํธ๋ ์ดํฐ(Kubernetes, Nomad ๋ฑ)์ ๊ฒฝ์ฐ:
| ํ๋ก๋ธ | ๊ถ์ฅ | ์ง์ |
|---|---|---|
| ๋ผ์ด๋ธ๋์ค | HTTP GET /livez ๋๋ ๊ธฐ๋ณธ ํฌํธ(PORT, ๊ธฐ๋ณธ๊ฐ 20128)์ TCP |
๋ผ์ด๋ธ๋์ค์ /api/monitoring/health ์ฌ์ฉ |
| ๋ ๋๋์ค | HTTP GET /healthz |
์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋ฐ์ ์ํ๋ฅผ ํ๋ก์ธ์ค ์ค๋จ์ผ๋ก ๊ฐ์ฃผํ๋ ์งง์ ํ์์์ |
| ์ฌ์ธต / ๋ธ๋๋ฐ์ค | /api/monitoring/health |
โ |
/healthz๋ ํ๋ก์ธ์ค ์๋ช
์ฃผ๊ธฐ ์ํ(ok / starting / stopping)๋ฅผ ๋ณด๊ณ ํฉ๋๋ค. /livez๋ ํ๋ก์ธ์ค์ ์์กด ์ฌ๋ถ๋ง ํ์ธํฉ๋๋ค(ํธ๋ค๋ฌ๊ฐ ์คํ๋ ์ ์์ผ๋ฉด ํญ์ 200์ ๋ฐํํ๋ฉฐ ๋ ๋๋์ค ์ํ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์์). ๋ ์๋ํฌ์ธํธ ๋ชจ๋ ์์ฒญ ์ฒ๋ฆฌ์ ๋์ผํ Node ์ด๋ฒคํธ ๋ฃจํ์์ ์คํ๋๋ฏ๋ก CPU ์ง์ฝ์ ์ธ ์นดํ๋ก๊ทธ ๋๋ ์์ถ ์์
์ผ๋ก ์ธํด ์๋ต์ด ์ง์ฐ๋ ์ ์์ต๋๋ค. ์ฆ, ๋ฐ์จ โ ์ค๋จ์
๋๋ค. HTTP ํ๋ก๋ธ๊ฐ ์๊ฐ ์ด๊ณผ๋๋ฉด TCP ๋ผ์ด๋ธ๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ ์ฒด ํ๋ก๋ธ ์ง์นจ:
๋ชจ๋ํฐ๋ง ๊ฐ์ด๋ โ Kubernetes ํ๋ก๋ธ ๊ถ์ฅ ์ฌํญ.
Caddy๋ฅผ ์ฌ์ฉํ Docker Compose (HTTPS ์๋ TLS)
์น์ ์ ๋ชฉ: โCaddy๋ฅผ ์ฌ์ฉํ Docker Compose (HTTPS ์๋ TLS)โCaddy์ ์๋ SSL ํ๋ก๋น์ ๋์ ์ฌ์ฉํ์ฌ OmniRoute๋ฅผ ์์ ํ๊ฒ ์ธ๋ถ์ ๊ณต๊ฐํ ์ ์์ต๋๋ค. ๋๋ฉ์ธ์ DNS A ๋ ์ฝ๋๊ฐ ์๋ฒ์ IP๋ฅผ ๊ฐ๋ฆฌํค๋์ง ํ์ธํ์ธ์.
services: omniroute: image: diegosouzapw/omniroute:latest container_name: omniroute restart: unless-stopped volumes: - omniroute-data:/app/data environment: - PORT=20128 # OAuth ์ฝ๋ฐฑ, ๋์๋ณด๋ ๋งํฌ ๋ฐ ์์ฑ๋ ๊ณต๊ฐ URL์ ์ํ ๋ธ๋ผ์ฐ์ ๋์ ์ค๋ฆฌ์ง์
๋๋ค. - NEXT_PUBLIC_BASE_URL=https://your-domain.com # ์์ฝ ์์
/์์ฒด ์์ฒญ์ ์ํ ๋ด๋ถ ์๋ฒ ๊ฐ URL์
๋๋ค. - BASE_URL=http://omniroute:20128 - AUTH_COOKIE_SECURE=true
caddy: image: caddy:latest container_name: caddy restart: unless-stopped ports: - "80:80" - "443:443" command: caddy reverse-proxy --from https://your-domain.com --to http://omniroute:20128
volumes: omniroute-data:Caddy๋ ์
์คํธ๋ฆผ ์ปจํ
์ด๋์ ํ์ค ์ ๋ฌ ํค๋๋ฅผ ์ค์ ํฉ๋๋ค. OmniRoute๋
OAuth ์ฝ๋ฐฑ ๋ฐ ์์ฑ๋ ๊ณต๊ฐ ๋งํฌ์ ์ ์ ๊ณต๊ฐ ์ค๋ฆฌ์ง์ผ๋ก NEXT_PUBLIC_BASE_URL์
์ฌ์ฉํฉ๋๋ค. ์ธ์ฆ๋ ๋์๋ณด๋ ์ฐ๊ธฐ ์์
์๋ ๋์ผ ์ถ์ฒ ์์ฒญ๊ณผ ์ธ์
์ ๋ฐ์ธ๋ฉ๋ CSRF
๋ณดํธ๊ฐ ์ ์ฉ๋ฉ๋๋ค. ๋ช
์์ ๊ตฌ์ฑ ๋์ ์ ๋ขฐํ ์ ์๋ ์ ๋ฌ ํค๋์์ ๊ณต๊ฐ ์ค๋ฆฌ์ง์
ํ์ํ๋๋ก OmniRoute๋ฅผ ์๋์ ์ผ๋ก ์ค์ ํ๋ ๊ณ ๊ธ ๋ฐฐํฌ์์๋ง OMNIROUTE_TRUST_PROXY๋ฅผ ํ์ฑํํ์ธ์.
Cloudflare Quick Tunnel
์น์ ์ ๋ชฉ: โCloudflare Quick TunnelโDocker ๋ฐฐํฌ์ฉ ๋์๋ณด๋๋ Dashboard โ Endpoints์์ ํด๋ฆญ ํ ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์๋ Cloudflare Quick Tunnel์ ์ง์ํฉ๋๋ค. ์ฒ์ ํ์ฑํํ๋ฉด ํ์ํ ๊ฒฝ์ฐ์๋ง cloudflared๋ฅผ ๋ค์ด๋ก๋ํ๊ณ , ํ์ฌ /v1 ์๋ํฌ์ธํธ๋ก ์์ ํฐ๋์ ์์ํ ๋ค์, ์์ฑ๋ https://*.trycloudflare.com/v1 URL์ ์ผ๋ฐ ๊ณต๊ฐ URL ๋ฐ๋ก ์๋์ ํ์ํฉ๋๋ค.
์๋ํฌ์ธํธ ํฐ๋ ํจ๋(Cloudflare, Tailscale, ngrok)์ ํ์ฑ ํฐ๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ Settings โ Appearance์์ ํ์ํ๊ฑฐ๋ ์จ๊ธธ ์ ์์ต๋๋ค.
ํฐ๋ ์ฐธ๊ณ ์ฌํญ
์น์ ์ ๋ชฉ: โํฐ๋ ์ฐธ๊ณ ์ฌํญโ- Quick Tunnel URL์ ์์์ด๋ฉฐ ๋ค์ ์์ํ ๋๋ง๋ค ๋ณ๊ฒฝ๋ฉ๋๋ค.
- OmniRoute ๋๋ ์ปจํ ์ด๋๋ฅผ ๋ค์ ์์ํ ํ์๋ Quick Tunnel์ด ์๋์ผ๋ก ๋ณต์๋์ง ์์ต๋๋ค. ํ์ํ ๊ฒฝ์ฐ ๋์๋ณด๋์์ ๋ค์ ํ์ฑํํ์ธ์.
- ๊ด๋ฆฌํ ์ค์น๋ ํ์ฌ
x64/arm64๊ธฐ๋ฐ Linux, macOS ๋ฐ Windows๋ฅผ ์ง์ํฉ๋๋ค. - ๊ด๋ฆฌํ Quick Tunnel์ ์ ์ฝ์ด ์๋ ์ปจํ
์ด๋ ํ๊ฒฝ์์ ๊ณผ๋ํ QUIC UDP ๋ฒํผ ๊ฒฝ๊ณ ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ธฐ๋ณธ์ ์ผ๋ก HTTP/2 ์ ์ก์ ์ฌ์ฉํฉ๋๋ค. ๋ค๋ฅธ ์ ์ก ๋ฐฉ์์ ์ฌ์ฉํ๋ ค๋ฉด
CLOUDFLARED_PROTOCOL=quic๋๋auto๋ก ์ค์ ํ์ธ์. - Docker ์ด๋ฏธ์ง๋ ์์คํ
CA ๋ฃจํธ๋ฅผ ํฌํจํ๊ณ ์ด๋ฅผ ๊ด๋ฆฌํ
cloudflared์ ์ ๋ฌํ๋ฏ๋ก, ์ปจํ ์ด๋ ๋ด๋ถ์์ ํฐ๋์ด ๋ถํธ์คํธ๋ฉ๋ ๋ ๋ฐ์ํ๋ TLS ์ ๋ขฐ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค. - OmniRoute๊ฐ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ค์ด๋ก๋ํ๋ ๋์ ๊ธฐ์กด ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฌ์ฉํ๋๋ก ํ๋ ค๋ฉด
CLOUDFLARED_BIN=/absolute/path/to/cloudflared๋ก ์ค์ ํ์ธ์.
์ด๋ฏธ์ง ํ๊ทธ
์น์ ์ ๋ชฉ: โ์ด๋ฏธ์ง ํ๊ทธโ| ์ด๋ฏธ์ง | ํ๊ทธ | ํฌ๊ธฐ | ์ค๋ช |
|---|---|---|---|
diegosouzapw/omniroute |
latest |
~250MB | ๊ฐ์ฅ ๋์ ๊ฒ์๋ ์์ SemVer(git main ์๋) |
diegosouzapw/omniroute |
3.8.0 |
~250MB | GitOps์์๋ ์ด ์ ํ์ ํ๊ทธ๋ฅผ ๊ณ ์ ํ์ฌ ์ฌ์ฉ |
๋ค์ค ํ๋ซํผ ๋งค๋ํ์คํธ: linux/amd64 + linux/arm64 ๋ค์ดํฐ๋ธ ์ง์(Apple Silicon, AWS Graviton, Raspberry Pi). Docker๋ ์ผ์นํ๋ ์ํคํ
์ฒ๋ฅผ ์๋์ผ๋ก ์ ํํฉ๋๋ค. ARM ํธ์คํธ์์ AMD64 ์๋ฎฌ๋ ์ด์
์ ๊ฐ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ --platform linux/amd64๋ฅผ ์ ๋ฌํ์ธ์.
๋ฆด๋ฆฌ์ค ์ฑ๋
์น์ ์ ๋ชฉ: โ๋ฆด๋ฆฌ์ค ์ฑ๋โOmniRoute๋ ์์ ๋ฆด๋ฆฌ์ค, ํ์ฑ ๋ฆด๋ฆฌ์ค ๋ธ๋์น ํ ์คํธ, ๊ฐ๋ฐ ๋น๋๋ฅผ ์ํ ๋ณ๋์ Docker ์ฑ๋์ ๊ฒ์ํฉ๋๋ค.
| ์ฑ๋ | ์์ค | ๋ณ๊ฒฝ ๊ฐ๋ฅ ์ฌ๋ถ | ๊ถ์ฅ ์ฉ๋ |
|---|---|---|---|
:<version> / :<version>-web |
์๋ช ๋๊ณ ๋ฒ์ ์ด ์ง์ ๋ ๋ฆด๋ฆฌ์ค | ๋ณ๊ฒฝ ๋ถ๊ฐ | ์ ํํ ๋ฆด๋ฆฌ์ค๋ฅผ ๊ณ ์ ํ๋ ํ๋ก๋์ ๋ฐฐํฌ |
:latest / :latest-web |
๊ฐ์ฅ ๋์ ๊ฒ์๋ ์์ SemVer | ๋ณ๊ฒฝ ๊ฐ๋ฅํ ์์ ํฌ์ธํฐ | SemVer ๊ฒ์ ์์
์ดํ ์์ ๋ฆด๋ฆฌ์ค๋ฅผ ์ถ์ โ main ๋๋ ๋ฆด๋ฆฌ์ค๋์ง ์์ release/v* ์ปค๋ฐ์ ์ถ์ ํ์ง ์์ |
:next / :next-web |
ํ์ฌ ๊ธฐ๋ณธ release/v* ๋ธ๋์น |
๋ณ๊ฒฝ ๊ฐ๋ฅํ ์ํํ ํฌ์ธํฐ | ํ์ฑ ๋ฆด๋ฆฌ์ค ๋ธ๋์น์ ๋ฐ์๋์์ง๋ง ์์ง ์์ ๋ฆด๋ฆฌ์ค์๋ ํฌํจ๋์ง ์์ ์์ ์ฌํญ ํ ์คํธ |
:main / :main-web |
main ๋ธ๋์น |
๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ๋ฐ ํฌ์ธํฐ | ๊ฐ๋ฐ ๋ฐ ํตํฉ ํ ์คํธ ์ ์ฉ |
์น ์ธ์
์ ๊ณต์: -web ์ด๋ฏธ์ง
์น์
์ ๋ชฉ: โ์น ์ธ์
์ ๊ณต์: -web ์ด๋ฏธ์งโ์์ ๋ชจ๋ ์ฑ๋์ -web ํ๊ทธ(:latest-web, :<version>-web, :next-web, :main-web)๋ ์ ๊ณตํ๋ฉฐ, ๋์ผํ ์ด๋ฏธ์ง์ Playwright์ Chromium ๋ธ๋ผ์ฐ์ ๊ฐ ์ถ๊ฐ๋ runner-web ์คํ
์ด์ง์์ ๋น๋๋ฉ๋๋ค. ์ผ๋ฐ ์ด๋ฏธ์ง๋ Chromium ์์ด ์ ๊ณต๋๋ฉฐ, gemini-web, claude-web, claude-turnstile์๋ Chromium์ด ํ์ํฉ๋๋ค.
์ค๋ฅ๋ ์์ ์์ ์ด ์๋๋ผ ๋์ค์ ๋ฐ์ํฉ๋๋ค. ์ด๋ฌํ ์ ๊ณต์๋ ๋ชจ๋ธ ๋ชฉ๋ก์ ํ์ํ๊ณ ๋์๋ณด๋์์ ์ฐ๊ฒฐ๋ ๊ฒ์ผ๋ก ๋ํ๋์ง๋ง, ์ฒซ ๋ฒ์งธ ์์ฒญ์์๋ง ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
[500]: Failed to load external module playwright: Error: Cannot find module'/app/node_modules/playwright/node_modules/playwright-core/browsers.json'์ด๋ฌํ ์ ๊ณต์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ฌ ์ฌ์ฉ ์ค์ธ ์ฑ๋์ -web ํ๊ทธ๋ฅผ ๊ฐ์ ธ์ค๋ฉด ๋ฉ๋๋ค. ๊ทธ ์ธ์๋ ์๋ฌด๊ฒ๋ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. npm/CLI ์ค์น(Docker ์ด๋ฏธ์ง ๋ฏธ์ฌ์ฉ)์์ ์ด์ ํด๋นํ๋ ๋๋ฝ ํญ๋ชฉ์ ๋ธ๋ผ์ฐ์ ๋ฐ์ด๋๋ฆฌ์
๋๋ค. ํธ์คํธ์์ npx playwright install chromium์ ์คํํ์ธ์.
์ํํ ์ฑ๋ ์ฌ์ฉ
์น์ ์ ๋ชฉ: โ์ํํ ์ฑ๋ ์ฌ์ฉโnext ์ฑ๋์ ํ์ฌ ๊ธฐ๋ณธ release/v* ๋ธ๋์น์ ํธ์ํ ๋๋ง๋ค ๋ค์ ๋น๋๋๋ฉฐ AMD64์ ARM64์ฉ์ผ๋ก ๋ชจ๋ ๊ฒ์๋ฉ๋๋ค. ์ด์ ์ ์ง๋ณด์ ๋ธ๋์น๋ ์ด ์ฑ๋์ ๋ฎ์ด์ธ ์ ์์ต๋๋ค. ์ด ์ฑ๋์ ๋ค์ ์์ ํ๊ทธ๊ฐ ์์ฑ๋๊ธฐ ์ ์ ํ์ฑ ๋ฆด๋ฆฌ์ค ๋ธ๋์น์ ๋ณํฉ๋ ์์ ์ฌํญ์ ํฌํจํ๋ ๊ฐ์ ธ์ค๊ธฐ ๊ฐ๋ฅํ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํฉ๋๋ค.
docker pull diegosouzapw/omniroute:nextdocker pull diegosouzapw/omniroute:next-webDocker Compose์์๋ ์ ํํ ํ๋กํ์ด ์ฌ์ฉํ๋ ์ด๋ฏธ์ง ํ๊ทธ๋ฅผ ์ฌ์ ์ํ ๋ค์, ์๋น์ค๋ฅผ ๊ฐ์ ธ์ ๋ค์ ์์ฑํ์ธ์.
services: omniroute: image: diegosouzapw/omniroute:nextdocker compose pulldocker compose up -d์์ ๋ฐ ๋กค๋ฐฑ
์น์ ์ ๋ชฉ: โ์์ ๋ฐ ๋กค๋ฐฑโnext๋ ์ ๋์ ์ธ ์ํํ ์ฑ๋์
๋๋ค. ํ์ฑ ๋ฆด๋ฆฌ์ค ๋ธ๋์น์ ํธ์ํ ๋๋ง๋ค ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฉฐ ํ๋ก๋์
์ฉ๋๋ก๋ ์ง์๋์ง ์์ต๋๋ค. ํน์ ๋น๋๋ฅผ ํ๊ฐํ๋ ๋์ ์ด๋ฏธ์ง ๋ค์ด์ ์คํธ๋ฅผ ๊ณ ์ ํ์ธ์.
docker pull diegosouzapw/omniroute:nextdocker image inspect diegosouzapw/omniroute:next --format '{{index .RepoDigests 0}}'ํ ์คํธํ๊ธฐ ์ ์ OmniRoute ๋ฐ์ดํฐ ๋ณผ๋ฅจ ๋๋ ๋ฐ์ธ๋ ๋ง์ดํธ๋ ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ฐฑ์ ํ์ธ์. ๋กค๋ฐฑํ๋ ค๋ฉด ์ด์ ์ ์ฌ์ฉํ ์์ ๋ฒ์ ๋๋ ๋ค์ด์ ์คํธ๋ฅผ ๋ณต์ํ๊ณ ์ปจํ ์ด๋๋ฅผ ๋ค์ ์์ฑํ์ธ์.
docker pull diegosouzapw/omniroute:<stable-version>docker compose up -d๋ฆด๋ฆฌ์ค ๋ธ๋์น ๋น๋๋ ์ ๋๋ก latest๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ์ ๊ฒฉํ ์์ ์๋งจํฑ ๋ฒ์ ๋ง ์์ ํฌ์ธํฐ๋ฅผ ์น๊ฒฉํ ์ ์์ต๋๋ค. next ์ด๋ฏธ์ง๋ ๋ฆด๋ฆฌ์ค ์ด๋ฏธ์ง ๊ฒ์ฌ์ ์ฐจ๋จ ๋ฐฉ์์ CRITICAL ์ทจ์ฝ์ ๊ฒ์ดํธ๋ฅผ ๊ทธ๋๋ก ์ ์งํฉ๋๋ค.
latest๋ git์ ์ต์ ์ํ๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค. main ๋๋ ํ์ฑ release/v* ๋ธ๋์น์ ๋ณํฉ๋ ์์ ์ฌํญ์ ์์ SemVer ์ด๋ฏธ์ง๊ฐ ๊ฒ์๋๊ณ ๊ฒ์ ์์
์ด :latest๋ฅผ ์น๊ฒฉํ๊ธฐ ์ ๊น์ง :latest์ ํฌํจ๋์ง ์์ต๋๋ค(ํด๋น SemVer์ ๋์ผํ ๋ค์ด์ ์คํธ). GitHub์ ์์ ์ฌํญ์ด ์ด๋ฏธ ํ์๋๋๋ฐ๋ latest๊ฐ ๊ทธ๋๋ก์ธ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค๋ฉด, :next๋ฅผ ๊ฐ์ ธ์ ๋ฆด๋ฆฌ์ค ๋ธ๋์น๋ฅผ ํ
์คํธํ๊ฑฐ๋ SemVer ํ๊ทธ๊ฐ ๋์ฌ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ธ์.
| ์ํ๋ ์ฌํญ | ์ฌ์ฉํ ํญ๋ชฉ |
|---|---|
| ๋ณ๊ฒฝ๋์ด์๋ ์ ๋๋ GitOps / ํ๋ก๋์ | :X.Y.Z(๋๋ ์ด๋ฏธ์ง ๋ค์ด์ ์คํธ) ๊ณ ์ |
| ๊ฒ์๋ ์์ ๋ฆด๋ฆฌ์ค๋ฅผ ์ถ์ ํ๊ณ ๋ฆด๋ฆฌ์ค๋ง๋ค ์ฌ์์ฑํ๋ ๊ฒ์ ํ์ฉ | :latest |
๋ฆด๋ฆฌ์ค๋์ง ์์ release/v* ์ปค๋ฐ ํ
์คํธ |
:next(ํ๋ก๋์
์ฉ ์๋) |
main ํ
์คํธ |
:main(ํ๋ก๋์
์ฉ ์๋) |
๊ฐ์ฉ์ฑ: ๊ธฐ๋ณธ SQLite๋ ๋จ์ผ ๋ ํ๋ฆฌ์นด ๊ตฌ์ฑ
์น์ ์ ๋ชฉ: โ๊ฐ์ฉ์ฑ: ๊ธฐ๋ณธ SQLite๋ ๋จ์ผ ๋ ํ๋ฆฌ์นด ๊ตฌ์ฑโ๊ธฐ๋ณธ Docker / Kubernetes OmniRoute๋ ํ๋์ Node ํ๋ก์ธ์ค + ํ๋์ SQLite writer๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ด ํ ํด๋ก์ง์์๋ ๊ณ ๊ฐ์ฉ์ฑ์ ์ง์ํ์ง ์์ต๋๋ค.
| ์ ์ฝ ์ฌํญ | ๊ฒฐ๊ณผ |
|---|---|
| ๋จ์ผ writer | ๋์ผํ SQLite ํ์ผ์ ๋ํด ์ฌ๋ฌ ๋ ํ๋ฆฌ์นด๋ฅผ ์คํํ์ง ๋ง์ธ์. DB๊ฐ ์์๋ฉ๋๋ค. |
| ์ฌ์์ฑ / ์ฌ์์ / HEALTHCHECK ์ข ๋ฃ | ์งํ ์ค์ธ SSE, ๋์๋ณด๋ ์ธ์
๋ฐ ์ธ๋ฉ๋ชจ๋ฆฌ ์ํ๊ฐ ์์ ํ ์ค๋จ๋ฉ๋๋ค. ์ฐ๊ฒฐ๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ์ด ๋์ด์ง๋๋ค. ์๋ํฌ์ธํธ๊ฐ ๋น์ด ์๋ ๋์์ ์ ์์ฒญ์ OmniRoute JSON์ด ์๋ ๋ฆฌ๋ฒ์ค ํ๋ก์์ **502 Bad Gateway: Unknown error**๋ฅผ ๋ฐ์ผ๋ฏ๋ก ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ฅผ ์ ๊ณต์ ์ฅ์ ์ ๊ตฌ๋ถํ ์ ์์ต๋๋ค(#11015). |
/healthz์ ๋์ผํ ์ด๋ฒคํธ ๋ฃจํ |
์ฌ์ฉ๋์ด ๋ง์ catalog ๋๋ compression tick์ผ๋ก ์ธํด probe๊ฐ ์ง์ฐ๋ ์ ์์ผ๋ฉฐ, timeout์ด ์งง์ผ๋ฉด ์ ์ผํ ๋ ํ๋ฆฌ์นด๊ฐ ์ฌ์์๋ฉ๋๋ค. |
Probe ๋งคํธ๋ฆญ์ค(Kubernetes probe ๊ถ์ฅ ์ฌํญ๋ ์ฐธ์กฐ):
| Probe | ๋์ | ์ฌ์ฉํ์ง ๋ง์์ผ ํ ํญ๋ชฉ |
|---|---|---|
| Liveness | PORT(๊ธฐ๋ณธ๊ฐ 20128)์ ๋ํ TCP ๋๋ ์ํ๋ HTTP /healthz |
/api/monitoring/health |
| Readiness | HTTP GET /healthz |
์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ฌ์ฉ ์ค์ธ ์ํ๋ฅผ ์ฅ์ ๋ก ์ทจ๊ธํ๋ ์งง์ timeout |
| ์ฌ์ธต ์ ๊ฒ / ์ฌ์ฉ์ | /api/monitoring/health |
์๋ํ๋ kubelet liveness |
์
๊ทธ๋ ์ด๋: ๋ชจ๋ ์ธ์
์ ์ฐ๊ฒฐ์ด ๋์ด์ง ๊ฒ์ผ๋ก ์์ํด์ผ ํฉ๋๋ค. ๊ฐ๋ฅํ๋ฉด ํด๋ผ์ด์ธํธ๋ฅผ drainํ์ธ์. ๊ธฐ๋ณธ SQLite์์๋ rolling update๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค. Compose์ restart: unless-stopped์ Docker HEALTHCHECK๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ปจํ
์ด๋๊ฐ Unhealthy ์ํ์ผ ๋ ์ ์ผํ ํ๋ก์ธ์ค๋ ๊ต์ฒด๋๋ฏ๋ก ์ํฅ ๋ฒ์๊ฐ ๋์ผํฉ๋๋ค.
๋จ์ผ ๋ ํ๋ฆฌ์นด์ฉ Kubernetes ์์(SQLite ํ์ผ ํ๋์ ๋ํด replicas๋ฅผ ๋๋ฆฌ์ง ๋ง์ธ์. Recreate๊ฐ ํ์์
๋๋ค):
spec: replicas: 1 strategy: type: Recreate template: spec: terminationGracePeriodSeconds: 90 containers: - name: omniroute lifecycle: preStop: exec: command: ["/bin/sleep", "15"] readinessProbe: httpGet: path: /healthz port: 20128 periodSeconds: 5 livenessProbe: tcpSocket: port: 20128 periodSeconds: 20preStop sleep์ ์ฌ์ฉํ๋ฉด SIGTERM ์ ์ kube๊ฐ Service ์๋ํฌ์ธํธ๋ฅผ ์ ๊ฑฐํ ์ ์์ผ๋ฏ๋ก ์๋ก์ด ํธ๋ํฝ์ด ์ข
๋ฃ ์ค์ธ ํ๋ก์ธ์ค๋ก ์ ๋ฌ๋์ง ์์ต๋๋ค. ์งํ ์ค์ธ /v1/responses SSE๋ heavyweight admission lease๋ฅผ ํตํด SHUTDOWN_TIMEOUT_MS(๊ธฐ๋ณธ๊ฐ 30์ด)๊น์ง drain๋ฉ๋๋ค(#11015). ์ฌ์ ํ ํ๋ก์ธ์ค์ ๋๋ฌํ๋ ์ ์์ฒญ์ 503 + Retry-After: 5๋ฅผ ๋ฐ์ต๋๋ค. ๋์ฒด ํ๋ก์ธ์ค๊ฐ Ready ์ํ๊ฐ ๋ ๋๊น์ง ๋ฐ์ํ๋ Recreate์ ๋น ์๋ํฌ์ธํธ ๊ตฌ๊ฐ์ ์ฌ์ ํ ์์ ํ ์๋น์ค ์ค๋จ์
๋๋ค. ์ด๋ probe ์ค์ ์ค๋ฅ๊ฐ ์๋๋ผ SQLite ํ ํด๋ก์ง์ ํน์ฑ์
๋๋ค.
์ธ๋ถ Postgres / multi-writer HA๋ ๋ฌธ์ํ๋ ๊ธฐ๋ณธ ์ง์ ๊ฒฝ๋ก๊ฐ ์๋๋๋ค. HA๊ฐ ํ์ํ๋ค๋ฉด ๋จ์ผ ๋ ํ๋ฆฌ์นด๋ฅผ ์ ์งํ๊ฑฐ๋ ํ๋ก์ ํธ์์ ๋ณ๋๋ก ํ
์คํธํ๊ณ ๋ฌธ์ํํ ํ ํด๋ก์ง๋ฅผ ์ฌ์ฉํ์ธ์. Postgres/MySQL ๊ด๋ จ ์์
์ #8075์์ ์งํ๋๊ณ ์์ต๋๋ค. ํด๋น ๊ธฐ๋ฅ์ด ์ถ์๋๊ธฐ ์ ๊น์ง ๋๊ท๋ชจ /v1/responses ์ฉ๋์ ํ์ฅํ๋ ์ ์ผํ๊ฒ ์ง์๋๋ ๋ฐฉ๋ฒ์ ํ๋์ ๋ณผ๋ฅจ์์ replicas > 1์ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ N๊ฐ์ ๋
๋ฆฝ ํ๋ก์ธ์ค๋ฅผ ์คํํ๋ ๊ฒ์
๋๋ค(๋ค์ ์น์
์ฐธ์กฐ).
์ค์ผ์ผ ์์: N๊ฐ์ ๋ ๋ฆฝ ํ๋ก์ธ์ค
์น์ ์ ๋ชฉ: โ์ค์ผ์ผ ์์: N๊ฐ์ ๋ ๋ฆฝ ํ๋ก์ธ์คโํ๋์ Node ํ๋ก์ธ์ค๋ ํ๋์ V8 ํ์
๋๋ค. ์๋ก ๊ฒน์น๋ ์ฝ 3โฏMiB / ์ฝ 750k-token ๊ท๋ชจ์ ์ฝ๋ฉ ์์ด์ ํธ POST /v1/responses ์์ฒญ ๋ ๊ฐ(RTK + Caveman)๋ ์ฝ 12โฏGi์์ ํด๋น ํ์ ์ค๋จ์ํค๋ฉฐ(FATAL ERROR: Reached heap limit), 16โฏGi cgroup์์ OOM์ ์ผ์ผํฌ ์ ์์ต๋๋ค. #7849๋ฅผ ์ฐธ์กฐํ์ธ์. ์ด ์ธก์ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์์ฐ์ ๋ํ ๊ฒฝ๊ณ ์ด์ง, ๋์์ ์คํ๋๋ ๊ธด /v1/responses ์์ฒญ์ ๋ ๊ฐ๋ก ์ ํํ๋ ์ ํ์ ํ๋ ์ต๋๊ฐ์ด ์๋๋๋ค. ๊ณ ๋ถํ ์ฑํ
์ ์๋ฝ ์ฌ๋ถ๋ ๋์ผํ V8/cgroup ์ํ์ ๊ธฐ๋ฐ์ผ๋ก ์๋ ์ฐ์ถ๋๋ ์์ ๋ฐ์ดํธ ์์ฐ(OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES, src/shared/middleware/admissionBudget.ts)์ ์ํด ์ ์ด๋ฉ๋๋ค. ์ด๋ฏธ ํฌ๊ธฐ๊ฐ ์กฐ์ ๋ ํ๋ก์ธ์ค์์ ์ด๋ฅผ ๋ ๋์ ๊ฐ์ผ๋ก ์ฌ์ ์ํ๊ฑฐ๋ ๋ ๊ฑฐ์ ์์ฒญ ์ ์ ํ์ธ OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT๋ฅผ ์ค์ ํ๋ฉด ์ค๋จ ๋ฌธ์ ๊ฐ ๋ค์ ๋ฐ์ํฉ๋๋ค. ์์ ์ฑํ
, /healthz, /v1/models, MCP๋ ์ด ์ ํ์ ํฌํจ๋์ง ์์ต๋๋ค.
๋จ์ผ ํ๋ก์ธ์ค: ๋ ๊ฐ๋ฅผ ์ด๊ณผํ๋ ๊ธด /v1/responses
์น์
์ ๋ชฉ: โ๋จ์ผ ํ๋ก์ธ์ค: ๋ ๊ฐ๋ฅผ ์ด๊ณผํ๋ ๊ธด /v1/responsesโ์ ์ ์ํ์ธ ํ๋ก์ธ์ค(ํ์ด OMNIROUTE_CHAT_ADMISSION_HEAP_SHED_RATIO, ๊ธฐ๋ณธ๊ฐ 0.75 ๋ฏธ๋ง)๋ ํ๋ก์ธ์ค ์ ์ฒด์ ์ฒ๋ฆฌ ์ค ๋ฐ์ดํธ ์์ฐ(OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES / #10110)์ ์ฌ์ ๊ฐ ์๋ ๊ฒฝ์ฐ, ๋์์ ๋ ๊ฐ๋ฅผ ์ด๊ณผํ๋ ๊ธด POST /v1/responses ์์ฒญ์ ์คํํ ์ ์์ต๋๋ค. OMNIROUTE_CHAT_LARGE_BODY_BYTES ์ด์(๊ธฐ๋ณธ๊ฐ 256โฏKiB)์ธ ๋ณธ๋ฌธ์ ๊ตฌ์กฐ๊ฐ ๋ณต์กํ ์์ฒญ๊ณผ ๋์ผํ ๊ณ ๋ถํ ๋ฆฌ์ค๋ฅผ ํ๋ํ๋ฉฐ, ๋์ผํ #10437 tryAcquireHealthyHeadroom ์ฐํ ๊ฒฝ๋ก(OMNIROUTE_CHAT_ADMISSION_HEALTHY_HEADROOM)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋์์ ์์ญ ๊ฐ์ ๊ธด SSE ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ์ ์ฒ๋ฆฌํ๋ ๊ฒ(์ด์์๋ ๋๊ฐ 40โ50๊ฐ๊ฐ ํ์ํจ)์ ๋ฉ๋ชจ๋ฆฌ ์์ฐ์ ๋ฌธ์ ์
๋๋ค. ์ฆ, ํ + ๊ธฐ๋ณธ/ํค๋๋ฃธ ์ฌ๋กฏ + OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํด์ผ ํ๋ฉฐ, ์ ํ์ ํ๋์ฝ๋ฉ๋ โ์ต๋ 2๊ฐโ ์ ํ์ ๋ฌธ์ ๊ฐ ์๋๋๋ค. ์๋ฐ์ ๋ฐ๋ ํ์ ์ฌ์๋ ๊ฐ๋ฅํ 503์ผ๋ก ๊ณ์ ์์ฒญ์ ์ฐจ๋จํ๋ฏ๋ก #7849 ๋ฌธ์ ๊ฐ ์ฌ๋ฐํ์ง ์์ต๋๋ค.
ํ ์๋ฅผ ๋๋ฆฌ๋ ค๋ฉด(๋ ๋ฆฝ์ ์ธ V8 old-space) ํ์ฌ๋ ๋ค์๊ณผ ๊ฐ์ด ํ์ธ์.
| ํด์ผ ํ ๊ฒ | ํ์ง ๋ง์์ผ ํ ๊ฒ |
|---|---|
๊ฐ๊ฐ ์์ฒด DATA_DIR / ๋ณผ๋ฅจ์ ์ฌ์ฉํ๋ N๊ฐ์ ์ปจํ
์ด๋/ํ๋ ์คํ |
ํ๋์ SQLite ํ์ผ์ ๋์์ผ๋ก replicas > 1 ์ค์ |
| ํ / ์ฒ๋ฆฌ ์ค ๋ฐ์ดํธ ์์ฐ์ ๊ธฐ์ค์ผ๋ก ๊ณ ๋ถํ ์ฒ๋ฆฌ ์ค ์์ฒญ ์ + ์ ์ ์ํ ํค๋๋ฃธ ํฌ๊ธฐ ์กฐ์ . 1โ2๊ฐ๋ ๋ณด์์ ์ธ #7849 ๊ธฐ๋ณธ๊ฐ์ผ ๋ฟ, ์ ํ์ ํ๋ ์ต๋๊ฐ์ด ์๋ | ํ๋ก์ธ์ค ํ๋์ 8๋ฐฐ์ RAM๊ณผ ๋ฌด์ ํ ์์ฒญ ์ ์ํ ํ ๋น |
์ ํ ์ฌํญ: ๊ณต์ ํ ๋น๋ ์นด์ดํฐ๋ฅผ ์ํด QUOTA_STORE_DRIVER=redis + QUOTA_STORE_REDIS_URL ์ฌ์ฉ |
Redis๋ฅผ ๊ณต์ SQLite๋ก ์ทจ๊ธ โ Redis๋ ๊ณต์ SQLite๊ฐ ์๋ |
| ๊ฐ ์ธ์คํด์ค์ ๊ณต๊ธ์ ์ํฌ๋ฆฟ ๋ณต์ (๋๋ ๋ถ๋ฆฌ๋ ๋์๋ณด๋ ์์ฉ) | ์ธ์คํด์ค ์ ์ฒด์ ๊ฑธ์ณ ํ๋์ ๋์๋ณด๋ / ํ๋์ ํธ์ถ ๋ก๊ทธ ๊ธฐ๋ |
| ์์์ ๋ก๋ ๋ฐธ๋ฐ์๋ฅผ ์๋จ์ ๋ฐฐ์น. API ํค ๋๋ ์ธ์ ๊ธฐ์ค ์คํฐํค ๋ผ์ฐํ ์ด๋ฉด ์ถฉ๋ถ | ๊ณต๊ธ์ ์ฒด๋ณ ํฌ๊ธฐ ์ธ์ ๋ฏธ๋ค์จ์ด๊ฐ ํ์ํ๋ค๊ณ ๊ฐ์ฃผ |
ํ๋์จ์ด ์ธก๋ฉด์์ ์ธ์คํด์ค๋น ๋์์ ์คํ๋๋ ๊ธด /v1/responses ์์ฒญ ์๋ ๋ฉ๋ชจ๋ฆฌ ์์ฐ์ ๋ฌธ์ ์
๋๋ค(ํ + ์ฒ๋ฆฌ ์ค ๋ฐ์ดํธ / #10110). ๋
๋ฆฝ์ ์ธ DATA_DIR N๊ฐ๋ ์ฌ์ ํ ํ ์๋ฅผ ๋๋ฆฝ๋๋ค. ํธ์คํธ RAM์ โN=8์ธ ํ๋์ 16โฏGi ํ๋โ๊ฐ ์๋๋ผ N ร cgroup์ ๊ฐ๋นํด์ผ ํฉ๋๋ค. ํ๋์ SQLite ํ์ผ์์ ์ ๋๋ก replicas > 1์ ์ฌ์ฉํ์ง ๋ง์ธ์.
Compose ์์(ํ ๋ ๊ฐ, ๋ณผ๋ฅจ ๋ ๊ฐ โ deploy.replicas: 2๊ฐ ์๋):
services: omniroute-a: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-a-data:/app/data] ports: ["20128:20128"] omniroute-b: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-b-data:/app/data] ports: ["20138:20128"]volumes: omniroute-a-data: omniroute-b-data:ํ๋ก์ธ์ค ๋ด ๋ฐ๋ ํฅ์(HTTP isolate ์ธ๋ถ์์์ ์์ถ)์ #11023์์ ๋ค๋ฃน๋๋ค. ๊ณต์ ์๊ตฌ ์ํ๋ฅผ ์ฌ์ฉํ๋ ํ๋์ ๋ ผ๋ฆฌ์ ํด๋ฌ์คํฐ๋ #8075์์ ๋ค๋ฃน๋๋ค.
์ค์ ์ฐธ๊ณ ์ฌํญ
์น์ ์ ๋ชฉ: โ์ค์ ์ฐธ๊ณ ์ฌํญโ- SQLite WAL ๋ชจ๋: OmniRoute๊ฐ ์ต์ ๋ณ๊ฒฝ ์ฌํญ์
storage.sqlite์ ์ฒดํฌํฌ์ธํธ๋ก ๊ธฐ๋กํ ์ ์๋๋กdocker stop์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค. ๋ฒ๋ค๋ก ์ ๊ณต๋๋ Compose ํ์ผ์๋ ์ด๋ฏธ 40์ด์ ์ข ๋ฃ ์ ์ ๊ธฐ๊ฐ์ด ์ค์ ๋์ด ์์ต๋๋ค. ์ด๋ฏธ์ง๋ฅผ ์ง์ ์คํํ๋ ๊ฒฝ์ฐ--stop-timeout 40์ ์ ์งํ์ธ์. DISABLE_SQLITE_AUTO_BACKUP: ์ ๊ธฐ/์ฐ๊ธฐ ์ ๋ฐฑ์ ์ ์ธ๋ถ์์ ๊ด๋ฆฌํ๋ ๊ฒฝ์ฐtrue๋ก ์ค์ ํ์ธ์. ๊ธฐ์กด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ ์๋ ์ฌ์ ํ ๋ณ๋์ ๋ด๊ตฌ์ฑ ์๋ ์์ ์ค๋ ์ท๊ณผ ๋๊ท๋ชจ ๋ง์ด๊ทธ๋ ์ด์ ๋ณดํธ ์ฅ์น๊ฐ ํ์ํฉ๋๋ค.- ๋ฐ์ดํฐ ์์์ฑ: ์ปจํ
์ด๋๊ฐ ๋ค์ ์์๋์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํค ๋ฐ ๊ตฌ์ฑ์ ์ ์งํ๋ ค๋ฉด ํญ์
/app/data์ ๋ณผ๋ฅจ์ ๋ง์ดํธํ์ธ์. - ํฌํธ ๊ตฌ์ฑ: ๊ธฐ๋ณธ ํฌํธ
20128์ ๋ณ๊ฒฝํ๋ ค๋ฉดPORTํ๊ฒฝ ๋ณ์๋ฅผ ์ฌ์ ์ํ์ธ์.
ํจ๊ป ๋ณด๊ธฐ
์น์ ์ ๋ชฉ: โํจ๊ป ๋ณด๊ธฐโ- VM ๋ฐฐํฌ ๊ฐ์ด๋ โ VM + nginx + Cloudflare ์ค์
- Fly.io ๋ฐฐํฌ ๊ฐ์ด๋ โ Fly.io์ ๋ฐฐํฌ
- ํ๊ฒฝ ๊ตฌ์ฑ โ ์ ์ฒด
.env์ฐธ์กฐ
HagiCode
HagiCode๋ ๊ตฌ์กฐํ๋ ์ํฌํ๋ก, ๋ค์ค ์์ด์ ํธ ์คํ, Hero Dungeon ๋ทฐ๋ฅผ ๊ฐ์ถ ์์ด์ ํธ ์ฝ๋ฉ ์์ ๊ณต๊ฐ์ ๋๋ค.
๋ ์ค๋งํธํ๊ณ ๋น ๋ฅด๋ฉฐ ์ฆ๊ฑฐ์ด ์์ด์ ํธ ์ํฌํ๋ก๋ก ์ ์ฉํ ์ํํธ์จ์ด๋ฅผ ๋ง๋์ธ์.

- Smart๊ตฌ์กฐํ๋ ์ํฌํ๋ก๋ ์๋๋ฅผ ์์ด๋์ด๋ถํฐ ๋ฐฐํฌ๊น์ง ์คํ ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ก ๋ฐ๊ฟ๋๋ค.
- Efficient๋ค์ค ์์ด์ ํธ ์ํฌํ๋ก๋ก ์กฐ์ฌ, ๊ตฌํ, ๊ฒํ ๋ฅผ ๋ณ๋ ฌ๋ก ์งํํฉ๋๋ค.
- FunHero Dungeon์ ๊ธด ์ฝ๋ฉ ์ธ์ ์ ์๊ฐ์ ์ด๊ณ ํ์ ์ ์ธ ๊ฒฝํ์ผ๋ก ๋ง๋ญ๋๋ค.