11. 배포와 운영
1. 구성
환경 변수
| 이름 |
설명 |
PUBLIC_ORIGIN |
https://<도메인> (Origin 검사, OAuth 리다이렉트, 공유 링크) |
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET |
디스코드 앱 |
SESSION_SECRET |
짧은 수명 서명 쿠키(OAuth state)용 32바이트 |
DB_PATH |
기본 /data/app.db |
PORT |
기본 3000 |
LOG_LEVEL |
info |
Caddy
encode zstd gzip
/assets/*: Cache-Control: public, max-age=31536000, immutable (파일명에 해시)
index.html: no-cache (배포 즉시 반영)
- 보안 헤더: CSP(04 문서 7절),
X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, HSTS.
- WebSocket 프록시는 Caddy 기본 지원. 연결 유지 시간 제한 없음.
2. 배포 절차
main에 커밋·푸시(Gitea tkrmagid/joke-app).
- 서버에서
git pull && docker compose -f deploy/docker-compose.yml up -d --build.
- 옛 컨테이너가 SIGTERM을 받으면
bye: restart 전송 후 종료(stop_grace_period: 15s), 새 컨테이너가 방 복구 후 시작.
- 확인:
/healthz(DB 열림, 방 복구 완료) 200, 로그에 오류 없음, 테스트 방 하나 만들어 오목 한 수.
- 문제가 있으면 이전 이미지 태그로 되돌림(
docker compose 이미지에 커밋 해시 태그).
3. 개발·테스트 환경
- 로컬:
bun install && bun run dev → 웹 Vite(5173) + 서버(3000), Vite가 /api·/ws를 서버로 프록시.
- 디스코드 로그인 없이도 게스트로 모든 기능 테스트 가능(디스코드 값이 없으면 버튼 숨김).
- 공용 테스트 서버(사용자가 직접 접속해 보는 곳)는 배포 위치가 정해지면 같은 compose로 띄운다.
4. 백업과 복구
- 매일 04:00
VACUUM INTO '/data/backup/app-YYYYMMDD.db', 14개 보관.
- 복구: 컨테이너 중지 → 백업 파일을
app.db로 복사 → 시작. 진행 중이던 방은 백업 시점 상태로 돌아간다.
5. 감시
/healthz 1분마다 확인(외부 업타임 감시 또는 호스트 cron), 실패 3번이면 알림(디스코드 웹훅, 선택).
- 지표
/internal/metrics는 Caddy에서 외부 차단.
- 로그: Docker json-file, 크기 제한 50MB × 5.
6. 정해야 할 것 (사용자 결정 필요)
| 항목 |
선택지 |
기본 제안 |
| 서버 위치 |
이 호스트 / .5 Docker 호스트 / 외부 VPS |
개발 중에는 이 호스트에서 테스트, 공개용은 사용자 결정 |
| 도메인 |
예: game.tkrmagid.kr |
사용자 결정(DNS 설정 필요) |
| 디스코드 앱 |
개발자 포털에서 생성 → client ID/secret, Redirect URI 등록 |
도메인 정해진 뒤 |