[fix] deploy: .env.example 그대로 쓰면 로컬 발행이 안 됐다 — DB_HOST 와 줄끝 주석
문서대로 `cp .env.example .env` → `docker compose up -d` → 발행을 걸면 게이트는 통과하고 발행만 실패한다. 두 함정이 겹쳐 있었다(둘 다 실측). - DB_HOST=127.0.0.1: 컨테이너 안의 127.0.0.1 은 그 컨테이너다. 증상이 고약하다 — API 는 /healthz 가 DB 를 안 보므로 200 healthy 로 뜨고 워커만 조용히 재시작을 반복한다. compose 기본값(host.docker.internal)을 기본으로 올리고, 127.0.0.1 은 네이티브 실행용이라고 적었다 - 줄 끝 주석이 값이 된다: env_file 은 `KEY= # 설명` 을 빈 값으로 읽지 않는다. Azure 를 끈 로컬에서 is_configured() 가 참이 되어 발행 잡이 업로드를 시도하고 죽었다 (Connection string is either blank or malformed). 같은 모양 5개를 윗줄로 올리고, 파일 머리에 규칙을 근거와 함께 박았다 검증: web4ai_db 신규 생성 + init.sql → compose up → demo_build.py 발행 게이트 통과 · published:true · http://localhost/s/<slug> 200.
This commit is contained in:
parent
d498d36ccf
commit
b665c34ac2
27
.env.example
27
.env.example
@ -1,10 +1,20 @@
|
|||||||
# cp .env.example .env 후 값을 채운다. .env 는 커밋되지 않는다.
|
# cp .env.example .env 후 값을 채운다. .env 는 커밋되지 않는다.
|
||||||
# 우선순위: 실제 환경변수(compose) > .env > 코드 기본값(config_models.py)
|
# 우선순위: 실제 환경변수(compose) > .env > 코드 기본값(config_models.py)
|
||||||
|
#
|
||||||
|
# ★ 값 뒤에 주석을 붙이지 않는다. compose 의 `env_file` 은 줄 끝 주석을 **값으로 읽는다** —
|
||||||
|
# `AZURE_STORAGE_CONNECTION_STRING= # 비우면...` 은 "빈 값"이 아니라 "# 비우면..." 이라는 값이다.
|
||||||
|
# 실측(2026-09-07): 그래서 Azure 를 끈 로컬에서 발행 잡이 업로드를 시도하고
|
||||||
|
# "Connection string is either blank or malformed" 로 죽었다. 게이트는 통과했는데 발행만 실패한다.
|
||||||
|
# 주석은 반드시 **윗줄**에 둔다.
|
||||||
|
|
||||||
# ── 공통 solution/backend · admin/backend (server_configs 가 읽는다)
|
# ── 공통 solution/backend · admin/backend (server_configs 가 읽는다)
|
||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
|
|
||||||
DB_HOST=127.0.0.1
|
# ★ compose 로 띄우면 `host.docker.internal` 이다 — 컨테이너 안의 127.0.0.1 은 그 컨테이너다.
|
||||||
|
# 127.0.0.1 은 백엔드를 **네이티브로**(.venv/bin/python) 돌릴 때만 맞다.
|
||||||
|
# 이 값을 그대로 두고 `docker compose up` 하면 API 는 healthz 200 으로 멀쩡해 보이는데
|
||||||
|
# 워커만 조용히 재시작을 반복한다(ConnectionRefusedError 5432) — 발행 잡이 영원히 안 돈다.
|
||||||
|
DB_HOST=host.docker.internal
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_USER=postgres
|
DB_USER=postgres
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
@ -17,12 +27,15 @@ JWT_REFRESH_SECRET=
|
|||||||
|
|
||||||
# 키가 비면 그 어댑터만 꺼진다. 서버는 뜬다.
|
# 키가 비면 그 어댑터만 꺼진다. 서버는 뜬다.
|
||||||
PERPLEXITY_API_KEY=
|
PERPLEXITY_API_KEY=
|
||||||
COLLECT_USE_PERPLEXITY=0 # Perplexity 채널 발견. 0=끔(기본)
|
# Perplexity 채널 발견. 0=끔(기본)
|
||||||
|
COLLECT_USE_PERPLEXITY=0
|
||||||
NAVER_CLIENT_ID=
|
NAVER_CLIENT_ID=
|
||||||
NAVER_CLIENT_SECRET=
|
NAVER_CLIENT_SECRET=
|
||||||
KAKAO_REST_API_KEY= # 미발급. 없으면 네이버 지역검색을 쓴다
|
# 미발급. 없으면 네이버 지역검색을 쓴다
|
||||||
|
KAKAO_REST_API_KEY=
|
||||||
GEMINI_API_KEY=
|
GEMINI_API_KEY=
|
||||||
TOUR_API_KEY= # 디코딩된 키(인코딩 키는 이중 인코딩된다)
|
# 디코딩된 키(인코딩 키는 이중 인코딩된다)
|
||||||
|
TOUR_API_KEY=
|
||||||
|
|
||||||
# 구글 로그인. 비우면 구글 로그인만 꺼진다(서버는 뜨고, 화면에 버튼도 안 뜬다).
|
# 구글 로그인. 비우면 구글 로그인만 꺼진다(서버는 뜨고, 화면에 버튼도 안 뜬다).
|
||||||
# Google Cloud Console > API 및 서비스 > 사용자 인증 정보 > OAuth 2.0 클라이언트 ID(웹 애플리케이션)
|
# Google Cloud Console > API 및 서비스 > 사용자 인증 정보 > OAuth 2.0 클라이언트 ID(웹 애플리케이션)
|
||||||
@ -46,8 +59,10 @@ GOOGLE_CLIENT_ID=
|
|||||||
# canonical·og:url·sitemap·IndexNow 가 전부 SITE_PUBLIC_HOST 를 쓴다.
|
# canonical·og:url·sitemap·IndexNow 가 전부 SITE_PUBLIC_HOST 를 쓴다.
|
||||||
# 로컬은 비워 둔다(기본값 localhost). 서버에 올릴 때만 실제 도메인을 적는다.
|
# 로컬은 비워 둔다(기본값 localhost). 서버에 올릴 때만 실제 도메인을 적는다.
|
||||||
# SITE_PUBLIC_HOST=web4ai.o2osolution.ai
|
# SITE_PUBLIC_HOST=web4ai.o2osolution.ai
|
||||||
INDEXNOW_KEY= # 비우면 색인 통보를 건너뛴다(발행은 정상)
|
# 비우면 색인 통보를 건너뛴다(발행은 정상)
|
||||||
AZURE_STORAGE_CONNECTION_STRING= # 비우면 로컬 발행만 한다
|
INDEXNOW_KEY=
|
||||||
|
# 비우면 로컬 발행만 한다
|
||||||
|
AZURE_STORAGE_CONNECTION_STRING=
|
||||||
AZURE_STORAGE_CONTAINER=
|
AZURE_STORAGE_CONTAINER=
|
||||||
AZURE_STORAGE_PREFIX=
|
AZURE_STORAGE_PREFIX=
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,32 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-09-07 — `.env.example` 그대로 쓰면 로컬 발행이 안 됐다 — 함정 둘
|
||||||
|
|
||||||
|
클론 직후 문서대로 `cp .env.example .env` 하고 `docker compose up -d` 한 다음 발행을 걸어 봤다.
|
||||||
|
**게이트는 통과하는데 발행만 실패한다.** 두 가지가 겹쳐 있었다.
|
||||||
|
|
||||||
|
**1) `DB_HOST=127.0.0.1`** — 컨테이너 안의 127.0.0.1 은 그 컨테이너다. compose 기본값은
|
||||||
|
`host.docker.internal` 인데 `.env` 가 그걸 덮어쓴다. 증상이 고약하다: API 는 `/healthz` 가
|
||||||
|
DB 를 안 보므로 **200 healthy** 로 뜨고, **워커만 조용히 재시작을 반복한다** — 화면은 멀쩡하고
|
||||||
|
발행 잡만 영원히 안 돈다.
|
||||||
|
|
||||||
|
**2) 줄 끝 주석이 값이 된다.** compose 의 `env_file` 은 `KEY= # 설명` 을 "빈 값"으로 읽지
|
||||||
|
않는다 — 값이 `"# 설명"` 이다. 그래서 Azure 를 끈 로컬에서 `is_configured()` 가 참이 되고
|
||||||
|
발행 잡이 업로드를 시도해 `Connection string is either blank or malformed` 로 죽었다.
|
||||||
|
같은 모양이 5개였다: `COLLECT_USE_PERPLEXITY`(값 `0` 이 `"0 # ..."` 가 된다) ·
|
||||||
|
`KAKAO_REST_API_KEY` · `TOUR_API_KEY` · `INDEXNOW_KEY` · `AZURE_STORAGE_CONNECTION_STRING`.
|
||||||
|
|
||||||
|
**고친 것** — `.env.example`: `DB_HOST` 기본값을 `host.docker.internal` 로 바꾸고 네이티브
|
||||||
|
실행 때만 127.0.0.1 이라는 것을 주석으로 남겼다. 값 뒤 주석은 전부 **윗줄로 올렸고**,
|
||||||
|
파일 머리에 "값 뒤에 주석을 붙이지 않는다" 를 근거와 함께 박았다.
|
||||||
|
|
||||||
|
**검증** — 새 DB(`web4ai_db`)에 `init.sql` 적용 → `docker compose up -d` → 워커 정상 기동 →
|
||||||
|
`scripts/demo_build.py` 로 발행: 게이트 통과 · `published: true` · 프리렌더가 굽고
|
||||||
|
`http://localhost/s/<slug>` 200. ★ 참고로 `demo_build.py` 는 자기 안에서 워커를 한 번 돌리는데,
|
||||||
|
compose 워커가 잡을 먼저 집어가므로 **스크립트 출력은 "게이트 거부"로 보인다** — 실제 결과는
|
||||||
|
`job.jobs.result` 와 워커 로그에 있다.
|
||||||
|
|
||||||
## 2026-09-07 — 숙박 예약 구성 — "실시간 예약" 섹션이 전화번호 한 줄이었다
|
## 2026-09-07 — 숙박 예약 구성 — "실시간 예약" 섹션이 전화번호 한 줄이었다
|
||||||
|
|
||||||
**왜**
|
**왜**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user