1. Dockerfile


e.g. Dockerfile (Next.js)

# 1) 빌드 스테이지
FROM node:20-alpine AS builder

# 작업 디렉터리 설정
WORKDIR /app

# 패키지 정의 및 잠금 파일 복사
COPY package.json package-lock.json ./

# 의존성 설치 (CI 모드로 정확히 재현)
RUN npm ci

# 소스 복사 및 빌드
COPY . .
RUN npm run build

# 2) 프로덕션 스테이지
FROM node:20-alpine AS runner

WORKDIR /app

# 빌드 결과물과 정적 파일만 복사
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package-lock.json ./package-lock.json

# 프로덕션 전용 의존성만 설치
RUN npm ci --omit=dev

# Next.js가 3000 포트를 사용하므로 노출
EXPOSE 3000

# 컨테이너 구동 시 실행 명령
CMD ["npm", "start"]

1-1) 빌드 스테이지

FROM node:20-alpine AS builder

WORKDIR /app

COPY package.json package-lock.json ./

RUN npm ci

COPY . .
RUN npm run build
  1. 베이스 이미지 설정

    node:20-alpine 이미지를 사용한다.

  2. 작업 디렉터리 지정

    WORKDIR /app으로 컨테이너 내부 작업 경로를 /app으로 설정한다.

  3. 패키지 파일 복사 및 의존성 설치

    COPY package.json package-lock.json ./
    RUN npm ci
    
  4. 애플리케이션 소스 복사 및 빌드

    COPY . .
    RUN npm run build
    

1-2) 프로덕션 스테이지

FROM node:20-alpine AS runner

WORKDIR /app

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package-lock.json ./package-lock.json

RUN npm ci --omit=dev

EXPOSE 3000

CMD ["npm", "start"]

  1. 베이스 이미지 재설정 동일하게 node:20-alpine 이미지를 사용하되, 이번에는 runner 단계로 명명한다.

  2. 빌드 결과물 복사

    COPY --from=builder /app/.next ./.next
    COPY --from=builder /app/public ./public
    COPY --from=builder /app/package.json ./package.json
    COPY --from=builder /app/package-lock.json ./package-lock.json
    
  3. 프로덕션 의존성 설치

    RUN npm ci --omit=dev
    
  4. 포트 노출 & 실행 명령

    EXPOSE 3000
    CMD ["npm", "start"]