posts

admin

Oct 1, 2025 updated Oct 1, 2025 admincssdeploymentdockerexpo

2025 03 12 - 20:50

아래는 현재 구성(도커파일, docker-compose, nginx.conf, deploy.sh 등)을 기준으로 전체 배포 플로우와 Next.js 배포 방식과의 차이점에 대해 상세하게 정리한 내용입니다.

전체 배포 플로우

  1. prod.dockerfile 빌드 단계 (Stage: builder) • 베이스 이미지 및 작업 디렉토리: node:20-alpine 이미지를 사용하여 작업 디렉토리 /app로 설정합니다. • 빌드 인자 및 이미지 라벨: • ARG VERSION을 통해 빌드 시 외부에서 버전 정보를 전달할 수 있습니다. • LABEL version=$VERSION는 해당 버전 정보를 이미지의 메타데이터에 저장하여 나중에 어떤 버전의 이미지인지 확인할 수 있게 합니다. • 의존성 설치: package.json과 잠금 파일들(yarn.lock, package-lock.json, pnpm-lock.yaml)을 복사한 후, 사용 중인 패키지 매니저에 따라 의존성을 설치합니다. • 소스 코드 복사 및 빌드: 전체 소스 코드를 /app에 복사한 후, npm run build를 실행하여 Vite를 사용한 프로덕션 빌드를 수행합니다. • 빌드 결과물은 설정에 따라 /app/build/client (또는 원하는 디렉토리)에 생성됩니다.

  2. prod.dockerfile 런타임 단계 (Stage: runner) • 베이스 이미지: nginx:stable-alpine 이미지를 사용합니다. • 빌드 결과물 복사: builder 단계에서 생성된 정적 파일들이 있는 디렉토리(/app/build/client)를 Nginx 기본 서빙 디렉토리인 /usr/share/nginx/html로 복사합니다. • Nginx 설정 적용: 커스텀 nginx.conf 파일을 컨테이너 내의 /etc/nginx/conf.d/default.conf에 복사합니다. • 이 설정 파일에서는 Nginx가 listen 5173;로 동작하며, • root /usr/share/nginx/html;와 try_files $uri $uri/ /index.html;를 통해 정적 파일을 서빙하고, 클라이언트 라우팅(react-router)을 지원합니다. • 포트 노출 및 실행: • EXPOSE 80 명령은 기본 nginx 이미지에서 사용하는 포트를 명시합니다. (※ 이 명령은 도커 이미지 메타데이터 역할만 하며, 실제 요청은 docker-compose에서 설정한 포트 매핑에 따라 처리됩니다.) • 마지막에 CMD ["nginx", "-g", "daemon off;"] 명령으로 Nginx를 포그라운드에서 실행하여 컨테이너가 계속 동작하도록 합니다.

배포 스크립트 (deploy.sh)의 흐름

  1. 프로파일 및 변수 설정: • 스크립트 실행 시 dev 또는 prod 인자를 받으며, 해당 인자에 따라 EC2 호스트, 도커 컴포즈 파일, 이미지 접미사 등이 설정됩니다. • version.txt 파일에서 버전 정보를 읽어와 VERSION 변수에 저장하고, APP_BASE와 IMAGE_SUFFIX를 결합하여 최종 컨테이너 이름 및 이미지 이름(APP_NAME)을 구성합니다.
  2. 도커 이미지 빌드: • docker build 명령어를 사용하여 prod.dockerfile을 빌드합니다. • 빌드시 --build-arg VERSION="${VERSION}"를 통해 버전 정보를 전달합니다.
  3. 이미지 저장 및 전송: • 빌드된 이미지를 docker save로 tar 파일로 저장합니다. • scp를 사용하여 tar 파일, docker-compose 파일, nginx.conf 파일을 EC2 서버로 전송합니다.
  4. EC2에서 배포 실행 (SSH 접속 후): • 원격 서버에서 환경변수 VERSION과 APP_NAME을 export합니다. • 기존에 실행 중인 컨테이너들을 docker-compose down으로 종료합니다. • 이전에 사용된 이미지를 삭제합니다. • 전송된 tar 파일을 docker load로 로드합니다. • docker-compose up -d 명령어로 새로운 컨테이너들을 백그라운드에서 실행합니다. • docker system prune -f로 불필요한 도커 리소스를 정리합니다.
  5. 최종 접속: • docker-compose 파일에서는 ports: - "8081:5173"으로 설정되어 있으므로, 외부에서는 EC2 호스트의 8081 포트로 접속하면 내부 컨테이너의 5173 포트(즉, Nginx가 리스닝 중인 포트)로 트래픽이 전달됩니다. • 따라서 사용자는 http://:8081/로 접속하여 Admin 애플리케이션에 접근합니다.

Next.js 배포와의 차이점

Next.js 배포 방식 (예시) • Node 서버 실행: • Next.js 애플리케이션은 서버 사이드 렌더링(SSR)이나 API 라우트 등 동적 처리가 필요할 수 있으므로, 빌드 후 Node.js 서버(server.js)를 실행합니다. • prod.dockerfile에서는 보통 EXPOSE 3000과 함께 환경변수(HOST=, PORT=3000)를 설정하고, CMD ["node", "server.js"] 명령으로 애플리케이션을 구동합니다. • 추가 nginx 리버스 프록시 (옵션): • 필요에 따라 별도의 nginx 컨테이너를 두어 SSL 종료, 캐싱, 로드밸런싱 등의 역할을 수행할 수 있습니다.

Admin (Vite + React Router) 배포 방식 • 정적 파일 서빙: • Admin 애플리케이션은 Vite로 빌드하여 HTML, CSS, JS와 같은 정적 파일들만 생성합니다. • 정적 파일은 Node.js 서버 없이도 Nginx 같은 경량의 정적 파일 서버를 통해 서빙할 수 있습니다. • nginx 사용 및 포트 매핑: • prod.dockerfile의 런타임 단계에서는 nginx:stable-alpine 이미지를 사용하여 빌드 결과물을 /usr/share/nginx/html로 복사하고, 커스텀 nginx.conf를 적용하여 정적 파일과 클라이언트 라우팅을 처리합니다. • 기본 nginx 이미지는 내부적으로 EXPOSE 80을 가지고 있지만, 실제 실행 시에는 nginx.conf에서 listen 5173;로 설정하고, docker-compose 파일에서 외부 8081 포트를 컨테이너 내부의 5173 포트에 매핑합니다. • 실행 명령어의 차이: • Next.js는 node server.js로 Node 서버를 실행하는 반면, Admin은 정적 파일 서빙을 위해 nginx -g "daemon off;"로 Nginx를 포그라운드 실행하여 컨테이너가 종료되지 않도록 합니다.

요약 • 빌드 단계: Node 컨테이너에서 소스 코드를 복사하고 의존성을 설치한 후, npm run build로 Vite 빌드를 실행하여 정적 파일(예: /app/build/client)을 생성합니다. • 런타임 단계: Nginx 컨테이너에 빌드 결과물을 복사하고, 커스텀 nginx.conf를 적용하여 /usr/share/nginx/html에 있는 정적 파일을 서빙합니다. Dockerfile에서는 EXPOSE 80을 명시하지만, 실제 컨테이너에서는 nginx.conf에 따라 5173 포트에서 요청을 받으며, docker-compose에서 외부 8081 포트와 연결됩니다. • 배포 스크립트 (deploy.sh): 로컬에서 도커 이미지를 빌드한 후 tar 파일로 저장, EC2에 전송하고, 원격 서버에서 기존 컨테이너를 종료한 후 새 컨테이너를 실행하여 배포를 완료합니다. • Next.js와의 차이점: Next.js는 동적 서버(SSR)를 실행하기 위해 Node.js를 사용하고, 일반적으로 3000번 포트를 사용하며, 경우에 따라 별도의 nginx 리버스 프록시를 구성합니다. 반면 Admin(Vite+React Router)는 정적 파일만 생성되므로 Node 서버가 필요 없고, Nginx를 통해 정적 파일을 효율적으로 서빙합니다. • Next.js에서는 CMD ["node", "server.js"]를 사용하지만, Admin에서는 CMD ["nginx", "-g", "daemon off;"]를 사용하여 Nginx를 포그라운드 실행합니다. • 포트 매핑의 차이도 존재하며, Next.js는 일반적으로 내부 3000번과 외부 3000번(또는 nginx 프록시를 사용)으로, Admin은 docker-compose에서 외부 8081번을 내부 5173번으로 매핑하여 사용합니다.

이와 같이 구성하면, deploy.sh 실행 시 로컬 빌드부터 EC2에 이미지 전송, 컨테이너 재시작, 최종 접속(예: http://:8081/)까지 자동으로 진행되며, Admin 애플리케이션은 Nginx를 통해 정적 파일이 서빙됩니다.