Docker

(트러블슈팅) Next.js 프로젝트 Docker 이용해 배포하기

무무11 2024. 12. 4. 20:38

여기에는 실제 프로젝트 중에 겪었던 문제에 대해 간단하게 정리해보려고 한다.

 

백엔드 뿐만 아니라 프론트의 배포 자동화까지 담당하게 되어 Next.js 프로젝트 역시 배포해야했는데 이때 문제가 발생했다.

 

사실 엄청 단순한 문제이고 Next.js에 대한 이해가 없는 상태에서 배포를 진행하느라 생긴 문제이다.

 

이미지를 빌드하기 위해 작성했던 Dockerfile은 대략 다음과 같다. (standalone 옵션을 이용해 이미지 용량을 줄였다)

FROM node:20 AS builder

WORKDIR /app

COPY package.json ./

RUN npm install

COPY . .

RUN npm run build

FROM node:20-alpine

WORKDIR /app

RUN npm install -g pm2

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

EXPOSE 3000

CMD ["pm2-runtime", "start", "server.js"]

위와 같은 Dockerfile을 이용해 이미지를 빌드하고 docker-compose.yml 설정 파일을 작성한 뒤 컨테이너를 띄웠다. 그런데 사이트가 제대로 동작하지 않았다.

 

문제는 쉽게 찾을 수 있었는데 설정 파일에서 값을 넣어준 환경변수에 값이 안들어갔기 때문이었다. 이미지를 빌드할 때는 환경변수가 필요없으니 생략했고, docker-compose.yml 파일에 환경변수를 잘 넣어주었다. 그런데 컨테이너를 띄워보면 환경변수에 값이 들어가지 않았다.

 

여러번 확인했지만 환경변수를 설정 파일에 잘 넣어주었는데 값을 찍어보면 undefined가 나왔다. 원인을 알지못해서 해결하기까지 시간이 좀 걸렸다.

 

조금 검색을 하다보니 다음과 같은 사실을 알 수 있었다.

 

https://nextjs-ko.org/docs/pages/building-your-application/configuring/environment-variables

 

"기본적으로, 환경 변수는 서버에서만 사용할 수 있다. 브라우저에서 환경 변수를 노출하려면 NEXT_PUBLIC_ 접두사를 붙여야합니다. 그러나 이러한 공개 환경 변수는 next build 중에 JavaScript 번들에 인라인됩니다. ... NEXT_PUBLIC_ 접두사가 없는 환경 변수는 Node.js 환경에서만 사용할 수 있으며, 브라우저에서는 액세스할 수 없습니다."

 

다시 말해 NEXT_PUBLIC_ 이라는 접두사가 붙어있는 환경변수의 경우는 빌드 시점에 하드코딩 되기 때문에 빌드 이후에 넣어줄 수 없다는 것이다.

 

해당 사실을 몰라서 env 파일에 있는 값들을 모두 이미지를 run 할 때 넣어주었는데 그래서 문제가 발생한 것이었다.

 

원인을 알았으니 문제는 쉽게 해결할 수 있었다. NEXT_PUBLIC_ 접두사가 붙어있는 환경변수를 빌드 시점에 넣어주도록 DockerFile을 수정했다.

FROM node:20 AS builder

WORKDIR /app

COPY package.json ./

RUN npm install

COPY . .

ARG NEXT_PUBLIC_BASE_URL # 추가

RUN npm run build

FROM node:20-alpine

WORKDIR /app

RUN npm install -g pm2

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

EXPOSE 3000

CMD ["pm2-runtime", "start", "server.js"]

저 값을 이제 빌드할 때 넣어주기만하면 해결된다.

 

Actions 워크플로우에서 아래와 같이 build-args로 값을 넣어주어 문제를 해결했다. (물론 워크플로우 작성 전에 로컬에서 환경변수를 넣어 빌드후 잘 작동하는지 테스트 해보았다.)

- name: Build Docker Image & Push
  uses: docker/build-push-action@v6
  with:
    context: .
    file: ./Dockerfile
    push: true
    tags: front-app:latest
    build-args: |
      NEXT_PUBLIC_BASE_URL=${{ secrets.NEXT_PUBLIC_BASE_URL }}

이렇게 문제를 잘 해결할 수 있었다.

 

 

여기까지 Next.js 프로젝트를 배포해야했지만 해당 프레임워크에 대한 이해가 부족해, 환경변수가 어떤 식으로 동작하는지 몰라서 배포시에 어려움을 겪었던 내용이다. 작업을 하면서 어떤 언어, 프레임워크로 되어있느냐에 따라 배포 작업에 약간 차이가 있기 때문에 여러 문제가 발생할 수 있다는 것을 알게되었다. 기회가 생겨 지금까지 Next.js, nest.js, Spring Boot(Kotlin, Java) 프로젝트를 배포해보게 되었는데 다양한 프로젝트를 경험해보게 되어 좋은 공부가 되었다고 생각한다.