Files
comrelay/docker-compose.yml
T
ttipo 38a3ecf8a2 build: LiveKit 을 공식 이미지 대신 소스(livekit-server/)에서 직접 빌드
- SFU 코어(pkg/sfu) 커스터마이즈를 위해 image: 참조를 build: 로 전환.
- 소스는 git subtree 로 v1.8.4 를 livekit-server/ 에 편입(이 레포에서 관리).
- 검증: 소스 빌드 이미지 99.8MB(공식 99.1MB 와 동일 수준),
  `livekit-server version 1.8.4` 정상 출력 → 코드 수정 없이 동일 동작 확인.
- dev 는 프로파일로 제외돼 무거운 Go 빌드가 돌지 않음(개발은 Cloud 유지).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:39:19 +09:00

193 lines
5.9 KiB
YAML

services:
# ----------------------------------------
# 1. Frontend (Nginx 정적 호스팅)
# ----------------------------------------
frontend:
container_name: ${PROJECT_NAME}-frontend
build:
context: ./${FRONTEND_DIR}
dockerfile: Dockerfile
args:
- BUILD_MODE=${BUILD_MODE}
- VITE_API_BASE_URL=${BACKEND_API_URL}
- VITE_AI_TIMEOUT_MS=${AI_TIMEOUT_MS}
# 브라우저가 접속할 LiveKit WebSocket URL
- VITE_LIVEKIT_URL=${LIVEKIT_WS_URL}
expose:
- "80"
environment:
- NODE_ENV=${APP_ENV}
restart: unless-stopped
networks:
- app-network
- proxy
depends_on:
- backend
healthcheck:
# localhost 는 일부 이미지에서 IPv6(::1) 로 먼저 풀려 IPv4 전용 바인딩에 연결 실패 → 127.0.0.1 고정
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:80/ || exit 1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 10s
deploy:
resources:
limits:
cpus: '0.5'
memory: 512m
# ----------------------------------------
# 2. Backend (HTTP API & WebSocket 통합)
# ----------------------------------------
backend:
container_name: ${PROJECT_NAME}-backend
build:
context: ./${BACKEND_DIR}
dockerfile: Dockerfile
expose:
- "${BACKEND_PORT}"
- "${WEBSOCKET_PORT}"
env_file:
- ./${BACKEND_DIR}/.env.${APP_ENV}
environment:
- NODE_ENV=${APP_ENV}
- PORT=${BACKEND_PORT}
- WEBSOCKET_PORT=${WEBSOCKET_PORT}
- CORS_ORIGIN=${CORS_ORIGIN}
- DB_HOST=db
- DB_PORT=5432
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- DB_NAME=${DB_NAME}
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
# AI 요청 타임아웃(ms) — 프론트(VITE_AI_TIMEOUT_MS)와 동일 값을 루트 .env 에서 공급
- AI_TIMEOUT_MS=${AI_TIMEOUT_MS}
# 화상회의(LiveKit) — 토큰 발급에 키/시크릿, 서버 API 호출에 내부 URL 사용
- LIVEKIT_API_KEY=${LIVEKIT_API_KEY}
- LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}
- LIVEKIT_URL=${LIVEKIT_URL}
restart: unless-stopped
networks:
- app-network
- proxy
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
# API 는 전역 프리픽스 /api 하위에 마운트됨 — 루트(/)는 404 라 /api/health 를 프로브.
# localhost→IPv6(::1) 회피를 위해 127.0.0.1 고정.
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:${BACKEND_PORT}/api/health || exit 1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
deploy:
resources:
limits:
cpus: '1.0'
memory: 1g
# ----------------------------------------
# 3. Database (PostgreSQL) — 내부 네트워크 전용
# ----------------------------------------
db:
container_name: ${PROJECT_NAME}-db
image: ${DB_IMAGE}
expose:
- "5432"
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- ${DB_DATA_DIR}:/var/lib/postgresql/data
restart: always
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
deploy:
resources:
limits:
cpus: '0.5'
memory: 512m
labels:
- "com.centurylinklabs.watchtower.enable=true"
# ----------------------------------------
# 4. Redis — 내부 네트워크 전용
# ----------------------------------------
redis:
container_name: ${PROJECT_NAME}-redis
image: ${REDIS_IMAGE}
command: redis-server --requirepass ${REDIS_PASSWORD}
expose:
- "6379"
volumes:
- ${REDIS_DATA_DIR}:/data
restart: always
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD} ping | grep PONG"]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
deploy:
resources:
limits:
cpus: '0.25'
memory: 256m
labels:
- "com.centurylinklabs.watchtower.enable=true"
# ----------------------------------------
# 5. LiveKit (화상회의 SFU) — 셀프호스팅 (운영 기본 서비스, 소스 직접 빌드)
# SFU 코어(pkg/sfu) 커스터마이즈를 위해 공식 이미지 대신 livekit-server/ 소스를
# 직접 빌드한다(git subtree, v1.8.4 기준). 소스·수정은 이 레포에서 관리한다.
# 운영(base)에서는 db·redis 처럼 항상 함께 기동된다.
# 개발(dev)에서는 docker-compose.dev.yml 이 selfhost-livekit 프로파일로 가두어
# 생성되지 않는다(개발은 LiveKit Cloud 사용).
# 배포·클러스터링 가이드: livekit/DEPLOY.md
# ----------------------------------------
livekit:
build:
context: ./livekit-server
dockerfile: Dockerfile
container_name: ${PROJECT_NAME}-livekit
command: --config /etc/livekit/livekit.yaml
environment:
# 키/시크릿은 "key: secret" 형식으로 주입(콜론+공백 때문에 전체를 따옴표로 감쌈)
- "LIVEKIT_KEYS=${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}"
expose:
- "7880" # 시그널링/HTTP API — 리버스 프록시(TLS)에서 wss 로 라우팅
ports:
- "7881:7881" # ICE/TCP 폴백
- "7882:7882/udp" # ICE/UDP (mux)
volumes:
# 클러스터링 시에는 redis 비밀번호가 담긴 사본을 마운트(DEPLOY.md 참고)
- ./livekit/livekit.prod.yaml:/etc/livekit/livekit.yaml:ro
restart: unless-stopped
networks:
- app-network
- proxy
deploy:
resources:
limits:
cpus: '2.0'
memory: 2g
networks:
app-network:
driver: bridge
proxy:
external: true