refactor(docker): simplify + optimize Dockerfile
- yt-dlp 를 ADD --chmod 로 빌드 타임에 받아 wget 설치/제거 단계 제거 - npm ci 에 BuildKit 캐시 마운트 추가로 재빌드 가속 - build/prune 레이어 통합, 장황한 주석 정리 Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
51
Dockerfile
51
Dockerfile
@@ -1,71 +1,48 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# ── 왜 Alpine 이 아니라 debian-slim(glibc) 인가 ──────────────────────────
|
# better-sqlite3 는 musl(Alpine) prebuilt 가 없어 빌드 체인이 필요하다.
|
||||||
# better-sqlite3 는 musl(Alpine) 용 prebuilt 바이너리를 배포하지 않는다.
|
# build 스테이지에서 컴파일한 node_modules 를 runtime 으로 복사해
|
||||||
# 그래서 Alpine 베이스에서 `npm install` 하면 prebuild-install 이 실패하고
|
# runtime 은 빌드 체인 없이 가볍게 유지한다 (glibc 베이스라 재현성도 좋다).
|
||||||
# node-gyp 풀 빌드로 떨어지는데, 빌드 체인(python3/make/g++)이 없으면
|
|
||||||
# "not found: make" 로 죽는다. 또한 better-sqlite3 의 특정 버전/Node ABI
|
|
||||||
# 조합은 glibc 에서도 prebuilt 가 없어 컴파일이 필요할 수 있다.
|
|
||||||
#
|
|
||||||
# 그래서 build 스테이지에 빌드 체인을 깔아 better-sqlite3 를 항상 소스에서
|
|
||||||
# 컴파일하고, 컴파일된 node_modules 를 runtime 스테이지로 복사한다.
|
|
||||||
# runtime 스테이지엔 빌드 체인이 없어 이미지가 가볍고, prebuilt 존재 여부에
|
|
||||||
# 의존하지 않아 어디서 빌드해도 재현 가능하다.
|
|
||||||
#
|
|
||||||
# Alpine 을 꼭 써야 한다면 같은 원리로 build 단계에
|
|
||||||
# RUN apk add --no-cache python3 make g++
|
|
||||||
# 를 깔고 runtime 엔 `apk add ffmpeg yt-dlp` 로 바꾸면 된다.
|
|
||||||
|
|
||||||
# ── build 스테이지: 네이티브 모듈 컴파일 + TS 빌드 ───────────────────────
|
# ── build: 네이티브 모듈 컴파일 + TS 빌드 ────────────────────────────────
|
||||||
FROM node:20-bookworm-slim AS build
|
FROM node:20-bookworm-slim AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# better-sqlite3 네이티브 컴파일용 toolchain.
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends python3 make g++ \
|
&& apt-get install -y --no-install-recommends python3 make g++ \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm ci
|
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||||
|
|
||||||
COPY tsconfig.json ./
|
COPY tsconfig.json ./
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
RUN npm run build
|
RUN npm run build && npm prune --omit=dev
|
||||||
|
|
||||||
# devDependencies 제거 — 컴파일된 better-sqlite3 .node 바이너리는 유지된다.
|
# ── runtime ──────────────────────────────────────────────────────────────
|
||||||
RUN npm prune --omit=dev
|
|
||||||
|
|
||||||
# ── runtime 스테이지 ─────────────────────────────────────────────────────
|
|
||||||
FROM node:20-bookworm-slim AS runtime
|
FROM node:20-bookworm-slim AS runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
# 앱 기본값(src/app.ts)은 HOST=127.0.0.1 이라 컨테이너 안에만 바인딩돼
|
# 앱 기본값 HOST=127.0.0.1 은 컨테이너 안에만 바인딩돼 포트 매핑이 안 먹는다.
|
||||||
# `docker run -p` 로도 호스트에서 못 붙는다. 컨테이너에선 0.0.0.0 으로 열어
|
|
||||||
# 포트 매핑이 동작하게 한다. (`docker run -e HOST=...` 로 덮어쓰기 가능)
|
|
||||||
ENV HOST=0.0.0.0
|
ENV HOST=0.0.0.0
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
|
|
||||||
# ffmpeg/ffprobe: 트림·60fps·FHD 변환. ca-certificates: yt-dlp https.
|
# ffmpeg: 트림·60fps·FHD 변환. ca-certificates: yt-dlp https.
|
||||||
# wget 은 yt-dlp 바이너리 받는 용도로만 쓰고 같은 레이어에서 제거.
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends ffmpeg ca-certificates wget \
|
&& apt-get install -y --no-install-recommends ffmpeg ca-certificates \
|
||||||
&& mkdir -p bin \
|
|
||||||
&& wget -qO bin/yt-dlp https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux \
|
|
||||||
&& chmod +x bin/yt-dlp \
|
|
||||||
&& apt-get purge -y wget && apt-get autoremove -y \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# build 스테이지에서 컴파일·프루닝된 node_modules 그대로 가져온다 (재컴파일 없음).
|
# yt-dlp 바이너리는 BuildKit 이 빌드 타임에 받아 넣는다 (이미지에 wget 불필요).
|
||||||
|
ADD --chmod=755 https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux bin/yt-dlp
|
||||||
|
|
||||||
COPY --from=build /app/node_modules ./node_modules
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
COPY --from=build /app/dist ./dist
|
COPY --from=build /app/dist ./dist
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
COPY public ./public
|
COPY public ./public
|
||||||
COPY views ./views
|
COPY views ./views
|
||||||
# 기본 admin 계정 파일. 운영에서는 볼륨/시크릿으로 덮어쓰세요 (초기값 admin).
|
# 기본 admin 계정 파일. 운영에선 볼륨/시크릿으로 덮어쓰세요 (초기값 admin).
|
||||||
COPY account.json ./account.json
|
COPY account.json ./account.json
|
||||||
|
|
||||||
# 영상/DB/잡 상태가 쌓이는 영속 디렉터리.
|
|
||||||
VOLUME ["/app/data"]
|
VOLUME ["/app/data"]
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
CMD ["node", "dist/app.js"]
|
CMD ["node", "dist/app.js"]
|
||||||
|
|||||||
Reference in New Issue
Block a user