상시 프리렌더와 중복 예약 안내를 없애고, 검수된 발행 버전을 보존한다. 미리보기는 실제 렌더 완료까지 스피너를 표시한다. 사이트 81건, 발행·롤백·서치콘솔 45건, 프로세스 수명 3건 통과. 빌더·사이트 빌드 및 compose 설정 검증 통과.
71 lines
4.4 KiB
Docker
71 lines
4.4 KiB
Docker
# 워커 전용 이미지 — solution-backend(:9800)·admin-backend(:9801) 와 **다른 이미지**다.
|
|
#
|
|
# ★ 왜 갈랐나 (프리렌더를 워커 실행으로 통합, 2026-09-15)
|
|
# BUILD·ROLLBACK 잡은 이제 컴파일된 Node 렌더러(solution/site)를 subprocess 로 직접
|
|
# 돌린다(services/render_service.py) — 예전에 별도 컨테이너(solution-prerender)가 하던
|
|
# 일이다. 그 렌더러가 필요한 건 **워커뿐**이다. Dockerfile(api/admin 겸용)에 Node 를
|
|
# 같이 넣으면 API 를 여는 요청만 받는 컨테이너에도 쓰지 않는 Node 런타임과 렌더러
|
|
# 번들이 실려 나간다 — 이미지가 커지고 공격 표면도 는다.
|
|
#
|
|
# ★ 기동·잡 실행 중에 npm install 을 하지 않는다. site-builder 스테이지가 이미지 빌드
|
|
# 시점에 한 번 굽고, 최종 이미지는 컴파일된 산출물만 COPY 한다.
|
|
# ★ node_modules 는 안 들어간다 — solution/site/vite.config.ts 가 SSR 번들에
|
|
# `ssr.noExternal: true` 로 react 등 의존성까지 전부 접어 넣는다(실측: node_modules 를
|
|
# 지우고 실행해도 그대로 돈다, dist/prerender/prerender.js 단일 파일 1.8MB).
|
|
#
|
|
# ★ 빌드 컨텍스트는 solution-backend 와 같은 **레포 루트**다 — solution/site 와
|
|
# solution/backend 를 한 이미지에 담아야 한다.
|
|
|
|
# ── 1단계: 렌더러 컴파일 (Node) ──────────────────────────────────────────────
|
|
FROM node:24-bookworm AS site-builder
|
|
WORKDIR /app
|
|
|
|
COPY package.json package-lock.json tsconfig.base.json ./
|
|
COPY solution/shared/package.json solution/shared/
|
|
COPY solution/frontend/package.json solution/frontend/
|
|
COPY solution/site/package.json solution/site/
|
|
COPY admin/frontend/package.json admin/frontend/
|
|
# ★ npm workspaces 는 루트 package.json 의 workspaces 목록에 있는 자리마다 package.json 을
|
|
# 요구한다 — site 만 빌드해도 4개를 전부 COPY 해야 npm ci 가 성공한다(nginx/Dockerfile 과 같다).
|
|
RUN npm ci
|
|
|
|
COPY solution/shared ./solution/shared
|
|
COPY solution/site ./solution/site
|
|
RUN npm run build:client -w @o2o/site \
|
|
&& npm run build:prerender -w @o2o/site
|
|
|
|
# ── 2단계: Node 런타임만 (바이너리를 뽑아 쓴다) ──────────────────────────────
|
|
# ★ python:3.12-slim 과 같은 계열(Debian bookworm)의 태그를 써야 한다 — glibc ABI 가
|
|
# 어긋나면 바이너리만 복사해서는 못 돈다("cannot execute binary file" 류로 죽는다).
|
|
FROM node:24-bookworm-slim AS node-runtime
|
|
|
|
# ── 3단계: 최종 워커 이미지 ───────────────────────────────────────────────
|
|
FROM python:3.12-slim-bookworm
|
|
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 로 같이 깐다.
|
|
RUN playwright install --with-deps chromium
|
|
|
|
# Node 바이너리만 옮겨 온다 — npm·corepack 은 쓰지 않는다(빌드는 site-builder 스테이지가
|
|
# 이미 끝냈다). /usr/local/bin/node 하나로 `node dist/prerender/prerender.js` 를 돌리는
|
|
# 데 충분하다(실측: 아래 COPY 만으로 `node --version` 과 렌더 스모크 테스트가 통과한다).
|
|
COPY --from=node-runtime /usr/local/bin/node /usr/local/bin/node
|
|
|
|
COPY solution/backend ./solution/backend
|
|
# ★ SITE_ROOT(solution/site/scripts/prerender.ts)가 자기 파일 위치 기준 상대경로로
|
|
# payloads·songs·out 을 찾는다 — dist·public 이 이 자리(/app/solution/site/)에 있어야
|
|
# 워커가 컨테이너 안에서 렌더러를 그대로 실행할 수 있다.
|
|
COPY --from=site-builder /app/solution/site/dist ./solution/site/dist
|
|
COPY --from=site-builder /app/solution/site/public ./solution/site/public
|
|
|
|
ENV APP_ENV=local
|
|
ENV PYTHONPATH=/app/solution/backend
|
|
WORKDIR /app/solution/backend
|
|
|
|
# 워커는 포트가 없다 — 이미지 공통 HEALTHCHECK 를 두지 않는다(compose 가 disable 한다).
|
|
CMD ["python", "worker_main.py"]
|