local
아래는 여러분의 Next.js 프로젝트를 로컬에서 빌드 후 EC2(또는 원격)와 내 로컬 Docker 환경에서 각각 배포할 수 있도록 준비한 파일 구성 및 배포 프로세스 예시입니다.
전체 배포 프로세스는 아래와 같이 진행됩니다.
- 필요한 파일 준비 • 프로덕션용 빌드를 위한 멀티 스테이지 Dockerfile • 개발/QA용(EC2) 배포를 위한 Compose 파일 (docker-compose.dev.yml) • 내 로컬 테스트용 Compose 파일 (docker-compose.local.yml) • (이미 준비된) 프로덕션용 Compose 파일 (docker-compose.prod.yml) • 배포 스크립트(예: deploy.sh): 로컬에서 빌드, Docker 이미지 생성 → tar 파일로 저장 → SCP 전송 → EC2에서 컨테이너 재시작
- 로컬 빌드 • Next.js 애플리케이션을 프로덕션 또는 개발 모드로 빌드 • Docker 이미지를 생성하고, 필요 시 tar 파일로 저장
- EC2에 Docker 이미지 배포 • SCP를 통해 tar 파일과 해당 docker-compose 파일을 전송
- EC2에서 컨테이너 시작 • 원격 서버에서 기존 컨테이너를 종료한 후 새로운 이미지를 로드 및 docker-compose로 실행
아래에 각 환경별로 사용할 파일들을 상세히 정리했습니다.
A. Dockerfile (프로덕션용 멀티 스테이지 빌드)
파일명: Dockerfile
용도: 프로덕션 배포용 이미지 생성 특징: Next.js를 next build로 빌드한 후 Standalone 모드 출력물을 포함하여 불필요한 파일을 제거
syntax=docker/dockerfile:1
1단계: 빌드 단계
FROM node:18-alpine AS builder
WORKDIR /app
의존성 파일 복사 (yarn, npm, pnpm 중 사용 중인 것을 자동 감지)
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
의존성 설치
RUN if [ -f yarn.lock ]; then yarn install --frozen-lockfile;
elif [ -f package-lock.json ]; then npm ci;
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install;
else echo "No lockfile found, installing via yarn" && yarn install; fi
프로젝트 전체 소스 복사
COPY . .
Next.js 프로덕션 빌드 실행
RUN npm run build
2단계: 런타임 단계 (프로덕션 실행 이미지)
FROM node:18-alpine AS runner
WORKDIR /app
보안을 위해 비 root 사용자 생성
RUN addgroup --system --gid 1001 nodejs &&
adduser --system --uid 1001 nextjs
USER nextjs
Standalone output 모드 사용: 빌드 산출물 중 필요한 부분만 복사
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/package.json ./
EXPOSE 3000
컨테이너 시작 시 Standalone 서버 실행 (빌드 산출물에 server.js 포함)
CMD ["node", "server.js"]
참고:
next.config.ts 파일에 아래와 같이 설정되어 있어야 합니다.
B. Dockerfile.dev (개발/로컬용)
파일명: Dockerfile.dev
용도: 개발 및 내 로컬 Docker 테스트용 이미지 생성 특징: 전체 소스를 복사하여 hot-reload 가능한 개발 서버(예: npm run dev)를 실행 (볼륨 마운트를 통해 코드 변경을 바로 반영할 수 있음)
syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
의존성 파일 복사
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
의존성 설치
RUN if [ -f yarn.lock ]; then yarn install;
elif [ -f package-lock.json ]; then npm install;
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install;
else echo "No lockfile found, installing via yarn" && yarn install; fi
소스 전체 복사 (개발 시 코드 수정 반영을 위해)
COPY . .
EXPOSE 3000
개발 모드 실행
CMD ["npm", "run", "dev"]
C. Docker Compose 파일들
프로덕션용 Compose
파일명: docker-compose.prod.yml 용도: EC2 등 실제 운영 환경에서 프로덕션 빌드 이미지로 컨테이너 실행
version: '3.8'
services: next-app: container_name: next-app-prod build: context: . dockerfile: Dockerfile environment: NODE_ENV: production ports:
- "3000:3000" restart: always networks:
- app-network
networks: app-network: driver: bridge
개발/QA용 Compose (EC2 배포 – QA 검수용)
파일명: docker-compose.dev.yml 용도: QA 검수를 위한 환경으로, 프로덕션 빌드(즉, Dockerfile 사용)를 그대로 사용하되 환경 변수나 컨테이너 이름 등으로 구분
version: '3.8'
services: next-app: container_name: next-app-dev build: context: . dockerfile: Dockerfile environment: NODE_ENV: development # QA 검수용으로 개발 환경 변수 사용 가능 (필요에 따라 "qa"로 설정) ports:
- "3000:3000" restart: always networks:
- app-network
networks: app-network: driver: bridge
로컬 테스트용 Compose (내 로컬 Docker에서 실행)
파일명: docker-compose.local.yml 용도: EC2 없이 내 로컬 Docker 환경에서 개발 서버(Hot Reload) 실행 특징: Dockerfile.dev를 사용하며, 소스 코드를 볼륨으로 마운트하여 실시간 변경 반영
version: '3.8'
services: next-app: container_name: next-app-local build: context: . dockerfile: Dockerfile.dev environment: NODE_ENV: development ports:
- "3000:3000" volumes:
- ./:/app # 로컬 소스 전체를 컨테이너에 마운트
- /app/node_modules # node_modules는 컨테이너 내부에서 관리 (호스트와의 충돌 방지) restart: always networks:
- app-network
networks: app-network: driver: bridge
D. 배포 스크립트 (예: Production 배포용 deploy.sh)
프로덕션(또는 QA) 배포 시, 로컬에서 빌드한 후 Docker 이미지를 tar 파일로 저장하고, SCP로 EC2에 전송한 후 EC2에서 컨테이너를 재시작하는 방식입니다.
파일명: deploy.sh
#!/bin/bash set -e
-------------------------
변수 설정 (필요에 따라 수정)
-------------------------
APP_NAME="my-nextjs-app" VERSION="latest" # 또는 버전 파일에서 읽어올 수 있음. LOCAL_IMAGE_NAME="${APP_NAME}:${VERSION}" REMOTE_IMAGE_PATH="/home/ec2-user/${APP_NAME}.tar"
배포할 docker-compose 파일을 선택: 프로덕션은 docker-compose.prod.yml, QA는 docker-compose.dev.yml
DOCKER_COMPOSE_PATH="/home/ec2-user/docker-compose.prod.yml"
PEM_FILE="
EC2 호스트 (예시: 운영 서버)
EC2_HOST="
-------------------------
1. 로컬 빌드 및 Docker 이미지 생성
-------------------------
echo "==== Next.js 프로덕션 빌드 시작 ====" npm run build || { echo "Next.js 빌드 실패"; exit 1; } echo "==== Next.js 빌드 완료 ===="
echo "==== Docker 이미지 빌드 (프로덕션) ====" docker build -t "$LOCAL_IMAGE_NAME" -f Dockerfile . echo "==== Docker 이미지 빌드 완료 ===="
-------------------------
2. Docker 이미지 tar 파일로 저장
-------------------------
echo "==== Docker 이미지 tar 파일로 저장 중 ====" docker save -o "${APP_NAME}.tar" "$LOCAL_IMAGE_NAME" echo "==== 이미지 저장 완료: ${APP_NAME}.tar ===="
-------------------------
3. EC2에 파일 전송 (이미지 tar와 선택한 docker-compose 파일)
-------------------------
echo "==== EC2에 파일 전송 시작 ====" scp -i "$PEM_FILE" "${APP_NAME}.tar" "$DEPLOY_USER@$EC2_HOST:$REMOTE_IMAGE_PATH" scp -i "$PEM_FILE" "$(basename $DOCKER_COMPOSE_PATH)" "$DEPLOY_USER@$EC2_HOST:$DOCKER_COMPOSE_PATH" echo "==== 파일 전송 완료 ===="
로컬에 생성된 tar 파일 삭제 (선택 사항)
rm "${APP_NAME}.tar"
-------------------------
4. EC2에서 이미지 로드 및 컨테이너 재시작
-------------------------
echo "==== EC2에서 배포 실행 ====" ssh -i "$PEM_FILE" "$DEPLOY_USER@$EC2_HOST" << 'EOF' set -e echo "==== 기존 컨테이너 종료 ====" docker-compose -f docker-compose.prod.yml down || true
echo "==== 기존 이미지 삭제 ====" docker images --filter=reference='my-nextjs-app:*' --format "{{.ID}}" | xargs -r docker rmi -f
echo "==== Docker 이미지 로드 중 ====" docker load -i /home/ec2-user/my-nextjs-app.tar
echo "==== Docker Compose 실행 ====" docker-compose -f docker-compose.prod.yml up -d
echo "==== 불필요한 Docker 리소스 정리 ====" docker system prune -f || true EOF
echo "==== 배포 완료 ===="
참고:
• QA용 배포 시 DOCKER_COMPOSE_PATH 값을 docker-compose.dev.yml로 변경하여 사용하면 됩니다.
• 로컬에서 직접 테스트할 때는 docker-compose.local.yml을 이용하여 docker-compose -f docker-compose.local.yml up --build 명령어로 실행합니다.
배포 프로세스 요약
- 필요한 파일 생성 • Dockerfile (프로덕션용)와 Dockerfile.dev (개발/로컬용) • docker-compose.prod.yml (운영), docker-compose.dev.yml (QA 검수용), docker-compose.local.yml (내 로컬 테스트용) • deploy.sh 스크립트 (프로덕션/QA 배포 자동화)
- 로컬 빌드 • 프로덕션 배포 시: npm run build → docker build -t my-nextjs-app:latest -f Dockerfile . • 개발/로컬 테스트 시: docker-compose -f docker-compose.local.yml up --build
- EC2에 Docker 이미지 배포 (프로덕션/QA) • deploy.sh 스크립트로 이미지 tar 파일 생성 → SCP로 EC2 전송
- EC2에서 컨테이너 시작 • SSH 접속 후, 기존 컨테이너 종료, 이미지 로드, docker-compose up 명령으로 컨테이너 재시작
이와 같이 구성하면, 여러분은 프로덕션, QA(개발), 그리고 내 로컬 테스트 환경에 맞게 배포 프로세스를 분리하여 관리할 수 있습니다.