Menu

메모용 개발 블로그

전체보기 > Docker >

nextjs docker image 경량화

2025-02-19 00:42:14

서론

개발 환경 및 기타 정보

  • Node: 22

  • next.js: 15.1.4

1. 컨테이너 이미지 변경

가장 먼저 고려해야할 요소는 컨테이너 이미지이다.

기반이 되는 배포판의 이미지가 가벼운 것을 사용하는 것이 좋다. 무난하게 alpine 리눅스를 흔히 사용한다.

node:22-alpine 이미지를 사용하고 있다.

node:22 이미지는 717.72 MiB

node:22-alpine 이미지는 387.45 MiB 가 나왔다.

330.27 MiB라는 차이가 발생하였으며 거의 절반에 가까운 감소를 보였다.

2. output: standalone

next 서버 구동을 위해서 불필요한 것을 빼고 필수요소만 정리하여 배포할 수 있다.

공식 문서는 아래 경로를 참고한다.

https://nextjs.org/docs/pages/api-reference/config/next-config-js/output

next.config.ts 파일을 연 다음 다음과 같이 수정한다.

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
    output: "standalone",
};

export default nextConfig;

이후 npm run build 명령어로 빌드를 수행하면 .next/standalone 경로에 빌드가 된다.

standalone 경로에는 프론트에 필요한 정적 파일이 존재하지 않는데.

이들은 수동으로 복사해주어야 한다. 대상하는 파일은 public, .next/static이다.

GitLab을 통한 배포를 수행하고 있으므로 다음과 같이 빌드를 수정해주었다.

(GitLab + GitLab Runner + GitLab Registry)

stages:
  - build-next
  - release-docker

Build Next App:
  stage: build-next
  image: node:22-alpine
  before_script:
    - npm ci --cache .npm --prefer-offline
  script:
    - npm i
    - npm run build
    - cp -r ./public ./.next/standalone
    - cp -r ./.next/static ./.next/standalone/.next
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - .npm/
  artifacts:
    expire_in: 3days
    paths:
      - .next/standalone
  tags:
    - docker

Release docker image:
  stage: release-docker
  image: docker:20.10.16
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
  resource_group: registry
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - .npm/
    policy: pull
  dependencies:
    - Build Next App
  tags:
    - docker-host

앞서 말한 것 처럼 정적파일들은 별도로 복사해주었다.

cp -r ./public ./.next/standalone
cp -r ./.next/static ./.next/standalone/.next

컨테이너 빌드를 위한 Dockerfile도 수정해주었다.

FROM node:22-alpine
RUN apk add curl
COPY ./.next/standalone /app/server
HEALTHCHECK --interval=10s --timeout=3s CMD curl -f http://localhost:3000 || exit 1
WORKDIR /app/server
CMD ["node", "/app/server/server.js"]

결과적으로 387.45 MiB에서 78.16 MiB 로 줄어들었다.

309.29 MiB 줄어들었다.

최종

위 과정을 수행하여서 639.56 MiB 용량을 줄일 수 있었다.

717.72 MiB - 78.16 MiB = 639.56 MiB