Files
joke-app/docs/11-deployment-ops.md

58 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 11. 배포와 운영
## 1. 구성
```
deploy/
├─ Dockerfile # 멀티 스테이지: bun install → web 빌드 → server 번들 → oven/bun:1-slim 실행 이미지
├─ docker-compose.yml # app + caddy, 볼륨: app-data(SQLite), caddy-data(인증서)
├─ Caddyfile # HTTPS 자동, /ws·/api → app:3000, 나머지 정적 파일
└─ .env.example # 필요한 환경 변수 목록(값 없음)
```
### 환경 변수
| 이름 | 설명 |
|---|---|
| `PUBLIC_ORIGIN` | `https://<도메인>` (Origin 검사, OAuth 리다이렉트, 공유 링크) |
| `DISCORD_CLIENT_ID` / `DISCORD_CLIENT_SECRET` | 디스코드 앱 |
| `SESSION_SECRET` | 짧은 수명 서명 쿠키(OAuth state)용 32바이트 |
| `DB_PATH` | 기본 `/data/app.db` |
| `SUPERADMIN_DISCORD_IDS` | 슈퍼어드민 디스코드 ID(쉼표 구분). 기본 `293719842274541579` |
| `TRUST_PROXY` | `1`이면 Caddy가 붙인 X-Forwarded-For로 IP 판단 |
| `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. 배포 절차
1. `main`에 커밋·푸시(Gitea `tkrmagid/joke-app`).
2. 서버에서 `git pull && docker compose -f deploy/docker-compose.yml up -d --build`.
3. 옛 컨테이너가 SIGTERM을 받으면 `bye: restart` 전송 후 종료(`stop_grace_period: 15s`), 새 컨테이너가 방 복구 후 시작.
4. 확인: `/healthz`(DB 열림, 방 복구 완료) 200, 로그에 오류 없음, 테스트 방 하나 만들어 오목 한 수.
5. 문제가 있으면 이전 이미지 태그로 되돌림(`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 등록 | 도메인 정해진 뒤 |