Feat: [main] hufs-notice-crawler CI/CD까지 구현 완료
All checks were successful
hufs-notice-crawler-cicd / build_push_deploy (push) Successful in 8m35s

This commit is contained in:
2026-03-17 17:18:16 +09:00
commit ca460453af
23 changed files with 1959 additions and 0 deletions

253
README.operation.md Normal file
View File

@@ -0,0 +1,253 @@
# 운영 문서
이 문서는 `HUFS 컴퓨터공학부 공지 크롤러`의 운영과 배포 절차를 설명합니다.
관련 문서:
- 서비스 개요: [`README.md`](/C:/Users/USER/Desktop/notice_crawler/README.md)
- 테스트: [`README.test.md`](/C:/Users/USER/Desktop/notice_crawler/README.test.md)
- n8n 연동: [`README.n8n.md`](/C:/Users/USER/Desktop/notice_crawler/README.n8n.md)
## PostgreSQL 준비
중요:
- `DB 자체는 직접 만들어야 합니다.`
- 앱이 자동으로 생성하는 것은 `테이블`까지입니다.
-`DATABASE_URL`로 접속할 데이터베이스는 미리 존재해야 합니다.
예:
```sql
CREATE DATABASE hufs_notice_crawler;
```
필요하면 사용자와 권한도 준비합니다.
```sql
CREATE USER crawler_user WITH PASSWORD 'your-password';
GRANT ALL PRIVILEGES ON DATABASE hufs_notice_crawler TO crawler_user;
```
## 호스트에서 Postgres 컨테이너로 DB 생성
컨테이너 이름 확인:
```bash
docker ps
```
예를 들어 PostgreSQL 컨테이너 이름이 `postgres`라면:
### 1. DB 생성
```bash
docker exec -it postgres psql -U postgres -d postgres -c "CREATE DATABASE hufs_notice_crawler;"
```
### 2. 사용자 생성
```bash
docker exec -it postgres psql -U postgres -d postgres -c "CREATE USER crawler_user WITH PASSWORD 'your-password';"
```
### 3. 권한 부여
```bash
docker exec -it postgres psql -U postgres -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE hufs_notice_crawler TO crawler_user;"
```
### 4. 확인
DB 목록:
```bash
docker exec -it postgres psql -U postgres -d postgres -c "\\l"
```
특정 DB 접속:
```bash
docker exec -it postgres psql -U postgres -d hufs_notice_crawler -c "\\dt"
```
처음에는 `\dt` 결과에 테이블이 없어도 정상입니다. 앱이 시작되면 필요한 테이블을 자동 생성합니다.
## 스키마 적용
스키마 파일:
- [`sql/schema.sql`](/C:/Users/USER/Desktop/notice_crawler/sql/schema.sql)
직접 적용하려면:
```bash
psql -h <POSTGRES_HOST> -U <POSTGRES_USER> -d <POSTGRES_DB> -f sql/schema.sql
```
정리:
- DB가 아직 없으면 먼저 `CREATE DATABASE`
- DB는 있고 테이블을 수동 생성하고 싶으면 `schema.sql` 적용
- DB는 있고 앱이 자동 생성하게 둘 거면 `schema.sql` 생략 가능
## bootstrap mode 운영 의미
이 서비스는 최초 실행 시 `scraped_posts` 테이블이 비어 있으면 `bootstrap mode`로 동작합니다.
판단 기준:
- `scraped_posts`에 행이 0개
- `bootstrap_mode = true`
- `scraped_posts`에 행이 1개 이상
- `bootstrap_mode = false`
bootstrap 동작:
- 기존 글을 저장만 함
- `new_posts_count = 0`
- `new_posts = []`
- `latest_posts_by_board``new_posts_count == 0`일 때만 포함
주의:
- `scraped_posts`를 전부 비우면 다음 호출은 다시 bootstrap 모드가 됩니다.
## Docker 이미지 빌드
```bash
docker build -t your-dockerhub-id/hufs-notice-crawler:latest .
```
버전 태그와 같이 빌드:
```bash
docker build -t your-dockerhub-id/hufs-notice-crawler:1.0.0 -t your-dockerhub-id/hufs-notice-crawler:latest .
```
## Docker Hub 로그인 및 push
로그인:
```bash
docker login
```
push:
```bash
docker push your-dockerhub-id/hufs-notice-crawler:1.0.0
docker push your-dockerhub-id/hufs-notice-crawler:latest
```
## 서버 배포
이 프로젝트는 Docker Hub 이미지를 `pull`해서 실행하는 구조입니다.
### 1. `.env` 준비
```env
APP_ENV=production
DB_USER=postgres
DB_PASSWORD=postgres
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=hufs_notice_crawler
BASE_URL=https://computer.hufs.ac.kr
REQUEST_TIMEOUT_SECONDS=15
MAX_PAGES_PER_BOARD=5
DOCKER_IMAGE=your-dockerhub-id/hufs-notice-crawler:latest
```
### 2. `docker-compose.yml` 확인
[`docker-compose.yml`](/C:/Users/USER/Desktop/notice_crawler/docker-compose.yml) 은 `build`가 아니라 `image pull` 기반입니다.
핵심 구조:
```yaml
name: nkeys-apps
services:
hufs-notice-crawler:
image: ${DOCKER_IMAGE}
env_file:
- .env
environment:
- DATABASE_URL=postgresql+psycopg://${DB_USER}:${DB_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
networks:
- nkeysworld-network
- obs
```
포인트:
- `name: nkeys-apps`
- 외부 네트워크 `nkeysworld-network`, `obs` 사용
- `ports:` 없음
- 같은 Docker network 내부 통신 전제
### 3. pull 및 실행
```bash
docker compose pull
docker compose up -d
```
업데이트 배포도 동일합니다.
## 내부 호출 URL
같은 Docker network 내부에서 직접 호출:
```text
http://hufs-notice-crawler:8000/api/v1/crawl
```
헬스체크:
```text
http://hufs-notice-crawler:8000/health
```
## nginx reverse proxy
nginx를 통해 외부에 노출할 경우 예시는 아래와 같습니다.
```nginx
location /api/hufs/ {
set $hufs_up http://hufs-notice-crawler:8000;
rewrite ^/api/hufs/crawl$ /api/v1/crawl break;
rewrite ^/api/hufs/health$ /health break;
proxy_pass $hufs_up;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120;
proxy_send_timeout 120;
}
```
외부 호출 URL:
- `POST https://nkeystudy.site/api/hufs/crawl`
- `GET https://nkeystudy.site/api/hufs/health`
주의:
- nginx 컨테이너도 `hufs-notice-crawler`와 같은 Docker network에 연결되어 있어야 합니다.
- 같은 network 내부에서만 통신할 거면 `ports:`는 열 필요가 없습니다.
## 로컬 개발 실행
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000
```