템플릿 정보가 빌더·렌더러·백엔드에 따로 적혀 어긋나 있었다 — 백엔드 기본값이 없는 id 를 가리켰고, 음식점 강조색 오타, 섹션 간격이 빌더와 서버에서 달랐다. - shared/src/data/templates.json: 템플릿 4개(simple·magazine·retro·paper)와 업종별 허용·기본 - shared/lib/catalog.ts · backend/common/template_catalog.py: 같은 JSON 을 읽는다, 모르는 id 는 에러 - 저장·미리보기·발행에서 모르는 id 를 거절한다(site_service · site.py 422 · build_service 실패) - site: 레이아웃 등록표(basic·paper) + LayoutProvider, Shell→Frame, HomePage→SectionList - 연결 안 된 레이아웃 5개, 배치 고르기(variant), 서체 선택, 빌더 canvas/DevShowcase 삭제 - 빌더: 템플릿을 바꾸면 이전 템플릿이 켠 섹션을 끄고 안내 문구를 띄운다 - postgres-init/migrations/0023: stay-retro → retro, 병원 허용 밖은 NULL(운영 미적용) - Dockerfile·worker: 백엔드 이미지에 shared/src/data 복사 - docs: TEMPLATES.md 신설(세 폴더 역할·템플릿 추가·렌더링 순서), DATA_MODEL·ARCHITECTURE 등 갱신 shared·site·frontend tsc 통과, site vitest 통과, 백엔드 DB 없는 테스트 41 passed(DB 테스트 미실행) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
46 lines
2.4 KiB
Docker
46 lines
2.4 KiB
Docker
# o2o-web4ai 백엔드 이미지 — 세 프로세스가 **같은 이미지**를 공유하고 command 로만 갈린다.
|
|
# 사장님 API : python web_main.py (:9800)
|
|
# 내부 API : python main.py (:9801, working_dir=/app/admin/backend)
|
|
# 워커 : python worker_main.py (수집·비전분석·빌드 잡, 포트 없음)
|
|
#
|
|
# ★ 빌드 컨텍스트가 **레포 루트**다(./solution/backend 가 아니다).
|
|
# 내부 API 진입점이 admin/backend 에 있고 도메인 코드는 solution/backend 에 있어서,
|
|
# 한 이미지에 둘 다 들어와야 한다. 나누면 requirements 를 두 번 설치하게 된다.
|
|
#
|
|
# 시크릿은 이미지에 굽지 않는다 — config 는 example(플레이스홀더)로 대체되고,
|
|
# 실제 값은 compose 의 env 로 주입된다(server_configs override).
|
|
FROM python:3.12-slim
|
|
|
|
WORKDIR /app
|
|
|
|
# 의존성 먼저 설치 (레이어 캐시 활용)
|
|
COPY solution/backend/requirements.txt .
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
# ★ yanolja_adapter.py 가 Playwright 로 페이지를 렌더링한다 — 패키지(pip)만으로는
|
|
# 브라우저 실행 파일이 없다. --with-deps 가 Chromium 이 필요로 하는 시스템 라이브러리
|
|
# (libnss3 등)까지 apt 로 같이 깐다. 세 프로세스(웹·admin·워커)가 이 이미지 하나를
|
|
# 공유하므로 실제로 fetch() 를 호출하는 건 워커뿐이어도 여기서 한 번만 설치한다.
|
|
RUN playwright install --with-deps chromium
|
|
|
|
COPY solution/backend ./solution/backend
|
|
COPY admin/backend ./admin/backend
|
|
COPY solution/shared/src/data ./solution/shared/src/data
|
|
|
|
|
|
ENV APP_ENV=local
|
|
# ★ 내부 API(admin/backend)가 common·router·services 를 그대로 import 하는 경로.
|
|
# 도메인 코드를 복제하지 않는 대신 이 한 줄이 두 폴더를 잇는다.
|
|
ENV PYTHONPATH=/app/solution/backend
|
|
|
|
# 기본은 사장님 API. 내부 API·워커는 compose 가 working_dir·command 를 갈아끼운다.
|
|
WORKDIR /app/solution/backend
|
|
|
|
EXPOSE 9800
|
|
|
|
# 사장님 API 컨테이너용. 워커는 포트가 없어 이 체크를 끄고, 내부 API 는 :9801 로 다시 건다
|
|
# (둘 다 compose 에서 override).
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:9800/healthz', timeout=4).status==200 else 1)"
|
|
|
|
CMD ["python", "web_main.py"]
|