[docker + nextjs] docker로 nextjs 배포시 docker image size 줄이기

minky·2023년 7월 23일
0
post-thumbnail

서문

마지막 글이 1년하고 1개월 전입니다. 제가 기술 블로그를 쓰기 어려워하는 사람인 줄 알았는데 그저 게으른 사람이란 걸 알게 되었습니다. 오늘은 최근 회사 리뉴얼 프로젝트에서 nextjs 도커 이미지 사이즈 및 빌드 타임 감소를 진행했던 경험을 공유하고자 합니다.

목차

  1. 문제점 파악
  2. 문제 해결
  3. 피드백

1. 문제점 파악

우선 이직할 때부터 존재하던 Dockerfile을 제대로 살펴보지 않았습니다. 도커에 대한 지식이 부족했고 디자인 시스템이 주 업무였기 때문에 안일했습니다. 그러던 중 시간이 갈수록 프론트엔드 파트에서도 devops 역할을 할 사람이 필요해졌고 이에 따라 공부하면서 파악한 기존 방식의 문제는 두 가지였습니다.

  1. next build 시 생성되는 .next 폴더와 node_modules를 모두 복사하고 있어 불필요하거나 중복하여 의존성을 가져가고 있다.
  2. next bulid 생성시 production 배포를 위한 설정인 standalone 속성을 사용하지 않았다.

입니다. 1번은 node_modules라는 거대한 의존성을 통째로 docker image로 옮기는 문제, 2번은 .next 역시 보다 경량화가 가능한 문제지만 사실 이는 모두 nextjs에서 제공하는 하나의 해결책을 통해 풀 수 있습니다.

2. 문제 해결

우선 기존 도커파일에서 문제가 되었던 부분을 살펴보겠습니다.

/* Dockerfile */ 
/* ...중략... */

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 80

CMD ["yarn", "start"]

실제로 현재의 .next 폴더는 node_modules를 가지고 있지 않기 때문에 개발환경 상의 node_modules를 복사하지 않는다면 배포한 웹사이트는 동작하지 않습니다. 이를 위해 nextjs는 standalone이라는 옵션을 제공합니다.

nextjs output 관련 공식문서 의 설명입니다.

Next.js can automatically create a standalone folder that copies only the necessary files for a production deployment including select files in node_modules. To leverage this automatic copying you can enable it in your next.config.js:
출처: nextjs output

이에 따라 next.config.js 에 아래와 같은 설정을 해주면 build 시 .next 파일에 standalone이라는 파일이 생성되고, 그 안에 배포시 꼭 필요한 node_modules를 생성해 줍니다.


module.exports = {
  output: 'standalone',
}

이 때 next.config.js는 next bulid 중에 읽혀 standalone 폴더 내에 들어있는 server.js file에 serialized 됩니다. 따라서 기존처럼 yarn start를 통해 build 폴더를 실행시키는 대신 server.js 파일을 직접 실행시킵니다.

원래라면 CMD ["node", "server.js"] 명령어를 통해 실행하면 끝입니다. 그러나 BE에서 사용하는 포트번호가 80번이고 containerPort와 hostPort를 통일할 필요가 있어 EXPOSE 80 및 taskdef.json의 port 설정을 바꾸는 대신 가장 간단한 방법인 server.js의 default 포트번호를 3000번에서 80번으로 변경하여 실행시키기로 했습니다. 다음은 변경된 Dockerfile 입니다.

/* Dockerfile */ 
/* ...중략... */

COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 80

CMD /bin/sh -c "PORT=80 node server.js"

이를 통해 다음과 같은 결과를 얻을 수 있었습니다.

<변경 전 - 2.79GB>
<변경 후 - 187.17MB>

3. 피드백

코드 수정은 크지 않았지만 큰 임팩트를 줄 수 있는 이슈였습니다. 결과적으로 해결의 실마리는 nextjs의 build 과정을 보다 잘 이해하고 제공하는 옵션을 활용하는 것에 있었습니다. 그러나 개인적으로 docker 와 aws 에 관해 무지하여 필요 이상의 시간을 소요 했습니다. 현타가 조금 와 냅다 udemy의 docker 강의와 aws 강의를 끊어서 수강하고 있으니 해당 포스트를 조금 더 발전시켜 다시 업로드할 날이 오리라 믿어 의심치 않습니다.

profile
프로덕트가 발전하는 과정을 즐기는 개발자입니다.

0개의 댓글