Commit Graph

5 Commits

Author SHA1 Message Date
민헌
8fa77af866 [chore] lps: 배포 설정 문서화 + 죽은 env 제거 + 알림 문구 정정
배포서버 쿠팡 크롤 조사(2026-07-28)에서 드러난 '설정한 줄 알았는데 아니었던' 것들 정리.
크롤 동작 자체를 바꾸는 변경은 없다.

- Dockerfile.worker: ENV LPS_CHROME_EXECUTABLE 제거.
  읽는 코드가 없는데 값이 박혀 있어 "컨테이너 Chrome 경로가 설정돼 있다"는 오해를 만들었다.
  경로의 유일한 소스는 [WorkerConfig].chrome_executable 이다(설정 시 --no-sandbox 동반).

- config.local.toml.example: profile_dir 경고 추가.
  컨테이너에서 ".profiles" 로 두면 /app/.profiles(컨테이너 레이어)에 쌓여 재생성마다 쿠키가
  날아가고, compose 가 마운트한 lps-profiles 볼륨은 붙어만 있고 아무 일도 하지 않는다.
  로컬·배포서버 양쪽에서 실측(/profiles 는 7/9·7/16 잔재, /app/.profiles 에 9MB 최신).

- config.prod.toml.example 신규: 배포서버 설정 템플릿.
  로컬과 다른 값만 ★ 표시. 헤더에 로드 경로의 함정을 명시했다 —
  docker-compose.prod.yml 이 이 파일을 config.local.toml 자리에 마운트하므로
  APP_ENV=local 인데도 내용은 prod 설정이다(파일명만 보면 오해한다).

- worker_main.py: budget_leak 알림이 "ip_request_budget 하향 검토"를 단정하던 것을 수정.
  차단이 ip_req#1 에 몰리면 새 IP 첫 요청부터 막히는 것이라 예산과 무관하다.
  bot_detection.ip_request_no 분포를 보고 처방을 고르도록 문구를 바꿨다.

⚠️ Dockerfile.worker 가 바뀌었으므로 배포 시 lps-worker 재빌드 필요.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 16:39:14 +09:00
f9d37e08f4 [fix] lps: 워커 이미지 chromium→google-chrome-stable 교체 (쿠팡 Akamai 지문 차단 회피) 2026-07-24 17:12:20 +09:00
민헌
a267326bf7 fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용
시크릿 유출 차단(핵심):
- config.local.toml(OpenAI·DECODO·네이버 키)이 COPY . . 로 이미지에
  구워지던 문제 — .dockerignore 제외 + 빌드 시 example(플레이스홀더)
  복사로 대체. 실값은 compose env 주입(리포 루트 .env, 템플릿 .env.example)
- DECODO_PORT_START/END/SESSION_MINUTES env override 추가 — 포트가
  toml(플레이스홀더 0)에만 있으면 자격증명을 넣어도 프록시가 조용히
  꺼지는 구멍 봉합

배포 견고화:
- API Dockerfile 에 HEALTHCHECK(/healthz) 추가
- autoheal 컨테이너 추가 — compose restart 는 unhealthy 를 재시작하지
  않으므로 라벨(autoheal=true) 기반 자동 재시작 담당
- 이미지 python 3.12→3.14 정렬(로컬 개발·테스트 환경과 일치)
- API 이미지 경량화: requirements-api.txt 분리(크롤 의존성 제거, 330MB)

검증: 양 이미지 빌드 성공, 이미지 내 시크릿·.profiles 부재 확인,
무시크릿 API 이미지 스모크(healthz/readyz/HEALTHCHECK healthy) 통과

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 11:53:47 +09:00
민헌
d6dd47e652 feat(lps): P4 관측·알림·워커 헬스 — readyz/ops + 하트비트/HEALTHCHECK + 임계 알림
프로덕션 운영 가시성. 행/좀비 워커 감지 + 큐/차단 지표 노출 + 임계 알림.

- API: /readyz(DB 도달성=readiness, 실패 503; /healthz=liveness와 구분).
  /v1/lps/ops(플랫 JSON): 큐 카운트 + oldest_pending_sec(큐지연) + dead_1h + stuck_running + blocks_1h.
- crud: JobQueue.ops()/ping(), BotDetectionLog.recent_count().
- worker: run_ops_monitor — 하트비트 파일 주기 갱신(Docker HEALTHCHECK 가 신선도로 행 워커 감지)
  + 임계(DEAD/차단/큐지연/stuck) 초과 시 WARN 로그 + (LPS_ALERT_WEBHOOK 있으면) Slack 호환 웹훅.
- Dockerfile.worker: HEALTHCHECK(하트비트 <120s). 임계·웹훅은 env(LPS_ALERT_*).
- 테스트: readyz/ops 2종.

검증: 컨테이너 healthy 판정, 하트비트 갱신, ops 스냅샷 정상. 91 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:21:43 +09:00
민헌
94d4e54d5e feat(lps): P1 컨테이너화 — 워커 이미지(Chromium+Xvfb) + compose
프로덕션 배포 토대. headless Chrome 은 Akamai/Cloudflare Turnstile 에 탐지됨(실측 실패)
→ 컨테이너에선 Xvfb(가상 디스플레이)로 headful Chromium 을 실행한다.

- Dockerfile.worker: chromium+xvfb+xauth+한글폰트. Xvfb 를 백그라운드로 띄우고 python 을
  exec 승계(로그가 docker logs 로 나옴; xvfb-run 은 stdout 을 삼킴). root=--no-sandbox 필수.
- Dockerfile: API 전용(lean, 브라우저 불필요)임을 명시.
- docker-compose: lps-api(:9600) + lps-worker(shm 1g, DB=host.docker.internal) 서비스 추가.
- browser_base: 브라우저 실행 대상 env 화(LPS_CHROME_EXECUTABLE/CHANNEL). 컨테이너=시스템
  chromium(+no-sandbox/disable-dev-shm-usage), 로컬=실제 Chrome(channel=chrome).

검증(컨테이너): DB연결·프리플라이트·쿠팡(Akamai)·gmarket(Turnstile) 웜업 통과 →
end-to-end 검색 DONE(8몰: 네이버·쿠팡·G마켓·옥션·11번가, 비용 $0.016). docker logs 로 로그 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 22:56:56 +09:00