# Operations Guide ## 배포 방식 ### Docker (수동) ```bash docker build -f dockerfile -t baekjoon-bot:prod . docker run -d --name baekjoon-bot \ --env-file .env \ -p 8000:8000 \ baekjoon-bot:prod ``` ### CI/CD (Gitea Actions) Workflow: `.gitea/workflows/cicd.yml` **트리거**: `main` 브랜치 push (문서 파일만 변경된 경우 스킵) **파이프라인**: 1. 수동 checkout (Gitea `/gitea` 서브패스 대응) 2. Docker Hub 로그인 3. 이미지 빌드/푸시: `${DOCKERHUB_USERNAME}/baekjoon-bot:latest` 4. 서버 배포: `/nkeysworld/compose.apps.yml`에서 `baekjoon-bot` 서비스 pull/up 5. 정리: `docker image prune -f` 6. Discord webhook 알림 (성공/실패) **필요 Secrets**: - `NKEY_PAT` - Gitea repo fetch 인증 - `DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN` - Docker Hub 인증 - `DISCORD_WEBHOOK` - 알림 전송 **서버 요구사항**: - `docker`, `docker compose` 실행 가능 - `/nkeysworld/compose.apps.yml` 파일 존재 - compose 내 서비스명 `baekjoon-bot` 존재 ## 운영 체크리스트 - `DATABASE_URL` 환경변수 필수 - Admin API 사용 시 `ADMIN_PASSWORD` 설정 필수 - 인바운드: TCP 8000 - 아웃바운드: solved.ac API, acmicpc.net 접근 필요 - DB 스키마는 별도 준비 필요 (레포에 DDL 미포함, `docs/DEVELOPMENT.md` 참고) - Uvicorn stdout 기반 로깅 ## 헬스체크 ```bash curl -s http://localhost:8000/ # {"status": "ok"} ``` ## 로그 확인 ```bash docker logs -f baekjoon-bot ``` ## 장애 대응 ### 1. DATABASE_URL 누락 - **증상**: 앱 시작 시 `DATABASE_URL is required...`로 즉시 종료 - **조치**: `.env` 또는 환경변수에 `DATABASE_URL` 설정 ### 2. 포트 충돌 - **증상**: `bind: address already in use` - **조치**: `-p 18000:8000` 등으로 호스트 포트 변경 ### 3. DB 연결 실패 - **증상**: API 호출 시 500, 로그에 DB 커넥션 에러 - **조치**: URL 확인, DB 접근 허용, DB 상태 확인 ### 4. Admin 인증 실패 - **증상**: admin API 403 `invalid admin password` - **조치**: `ADMIN_PASSWORD` 값과 `X-Admin-Password` 헤더 일치 확인 ### 5. 문제집 소진 - **증상**: 409 `no_more_problems_in_workbook` - **조치**: `DELETE /admin/workbooks/{id}/reset`으로 초기화하거나 다른 문제집 사용 ## 보안 - Admin API는 `X-Admin-Password` 헤더 기반 단일 비밀번호 인증 - `ADMIN_PASSWORD` 미설정 시 admin API는 500 반환 (의도적 차단) - `.env` 파일은 `.gitignore`에 포함 ## 롤백 CI/CD는 `:latest` 태그만 사용하므로, 롤백이 필요한 경우: - compose 파일에서 특정 태그로 고정하거나 - 태그 전략을 도입해야 한다