Files
rup/backend/Dockerfile
ttipo f60654bed6 chore(docker): 운영 배포 점검 반영 — 헬스체크·업로드 권한·빌드 컨텍스트·e2e 직렬 실행
운영 스택을 따로 띄워 확인하다 드러난 것들을 막는다.
- 업로드 디렉터리가 root 소유로 생기면 사진 업로드가 전부 500 인데 헬스체크(/)는 healthy 였다
  → 운영 헬스체크를 /api/health(DB) + 업로드 쓰기 권한으로, 이미지에 node 소유 디렉터리를 만들어 둔다
- 빌드 컨텍스트에 호스트(Windows) node_modules 와 backend/.env.* 가 들어가고 있었다 → .dockerignore
- CI e2e 는 스위트마다 빈 DB 에 마이그레이션을 동시에 돌려 충돌하고 재연결 타이밍으로만 통과했다 → --runInBand
- dev 헬스체크는 쿼리 로그가 쌓이지 않게 / 로 둔다
- 첫 배포 준비(env 두 파일·proxy 네트워크·업로드 디렉터리·백업·셸 APP_ENV 주의)를 docker 스킬에 적는다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:56:24 +09:00

44 lines
1.5 KiB
Docker

FROM node:20-alpine AS builder
WORKDIR /app
# 호스트의 npm 11 이 작성한 package-lock.json 형식과 호환되도록 npm 을 11 로 업그레이드
# (전역 설치는 root 권한이 필요하므로 USER 전환 전에 수행)
RUN npm install -g npm@11
# 개발 환경(docker-compose.dev.yml)은 이 스테이지를 그대로 구동하므로 비-root 로 전환한다.
# /app 소유권을 넘겨야 익명 볼륨(node_modules)도 node 소유로 생성되어 캐시 쓰기가 가능하다.
RUN chown node:node /app
USER node
# 재현 가능한 빌드를 위해 npm ci 사용 (lockfile 기반)
COPY --chown=node:node package*.json ./
RUN npm ci
COPY --chown=node:node . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
# 운영 stage 도 동일 npm 버전 사용
RUN npm install -g npm@11
# 운영용 의존성만 설치
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=builder /app/dist ./dist
# 업로드 저장 위치(compose 의 UPLOAD_DIR) — node 가 쓸 수 있게 소유권을 넘겨 둔다.
# named volume 은 이 소유권을 이어받는다. 호스트 경로(bind mount)는 호스트 디렉터리 소유권을 따르므로
# 운영 서버에서 미리 uid 1000 소유로 만들어 둔다 (.env.production.example 의 UPLOAD_DATA_DIR 참조)
RUN mkdir -p /app/uploads && chown node:node /app/uploads
EXPOSE 3000
# 비-root 실행 (보안 규칙)
USER node
CMD ["node", "dist/main"]