Docker는 애플리케이션을 컨테이너 내부에 배치할 수 있게 해 주는 기능으로 최근 몇 년간 인기를 얻었습니다. 이러한 컨테이너는 모든 환경에 배포할 수 있으며 모든 환경에서 동일한 방식으로 작동하여 애플리케이션이 실행되는 플랫폼에 관계없이 균일한 동작을 제공합니다. 이러한 컨테이너는 애플리케이션의 사본 또는 압축된 스냅샷인 이미지를 사용합니다. 컨테이너 안에 넣으면 그대로 표시됩니다. 이는 일부 사람들이 절실히 원했던 기술 중 하나이지만, 다른 사람들은 이 기술에 대해 듣기 전까지는 그 필요성을 깨닫지 못합니다.
Next.js는 가장 인기 있는 React 프레임워크입니다. webpack 또는 Vite와 같은 번들러를 사용하는 다른 JavaScript 애플리케이션과 마찬가지로 프로덕션에는 프로젝트의 컴파일된 버전이 사용됩니다. 이것을 빌드라고 합니다. 빌드는 애플리케이션이 개발 시와 동일하게 작동하는 데 필요한 최소한의 코드를 제공하는 것을 목표로 합니다. 이렇게 하면 JavaScript 파일이 매우 가벼워져 브라우저가 가능한 한 가장 짧은 시간에 해당 파일을 가져와 해석하여 사용자 인터페이스를 렌더링하거나 애플리케이션에 필요한 모든 작업을 수행할 수 있습니다."
특히 Next.js는 빌드 크기를 더욱 줄이는 버전인 독립 실행형 빌드를 제공합니다. Docker를 사용하여 Next.js 애플리케이션용 이미지를 생성하면 호환성이나 추가 구성에 대한 걱정 없이 모든 환경에 구축한 훌륭한 애플리케이션을 쉽게 배포할 수 있습니다. 이 기사에서는 이를 달성하는 방법을 살펴보겠습니다.
저의 경우 node_modules 폴더의 디스크 크기를 줄이기 위해 pnpm을 사용하는 것을 좋아합니다. 따라서 Next.js Docker 이미지의 예에서는 이 패키지 관리자를 사용하지만 원하는 경우 npm 또는 Yarn을 사용하도록 약간 조정할 수 있습니다.
next.config.js 파일에서는 애플리케이션이 프로덕션용으로 컴파일될 때 결과 빌드 유형이 독립형이 되도록 지정해야 합니다. 이를 위해서는 다음을 포함해야 합니다:
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
이렇게 하면 애플리케이션의 출력이 독립형 유형이 됩니다.
Docker 이미지를 나타내는 파일이 Dockerfile입니다. 일반적으로 이 파일은 프로젝트의 루트에 배치됩니다. 차근차근 만들어 보겠습니다.
모든 Docker 이미지는 기본 이미지에서 시작됩니다. 이 경우 서버를 실행하는 모든 JavaScript 프로젝트에는 Node.js와 같은 런타임이 필요합니다. 우리 프로젝트와 호환되는 Node.js 버전의 Docker 이미지를 기본으로 사용하겠습니다. 내 경우에는 Alpine 버전의 이미지를 사용하는 것이 더 가벼우므로 사용하는 것을 좋아합니다. 그러나 이미지를 빌드할 때 호환성 문제가 없는지 확인해야 합니다. 그렇지 않으면 "Alpine이 아닌" 이미지 버전을 사용해야 합니다. 이 예에서는 node:22.6.0-alpine3.19 이미지를 기본으로 사용합니다.
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
이미지의 여러 단계에서 재활용하기 위해 별칭을 배치합니다.
다음 단계는 종속성을 설치하는 것입니다. 이 경우 하나의 시스템 종속성(libc6-compat)만 필요합니다. 여기에 그 이유가 언급되어 있습니다.
FROM node:22.6.0-alpine3.19 AS base
Node.js에는 pnpm이 기본적으로 포함되어 있지 않기 때문에 pnpm을 활성화하고 설치된 패키지를 캐시할 수 있도록 환경변수를 설정해야 합니다.
FROM base AS build-deps RUN apk add --no-cache libc6-compat
그런 다음 시스템 폴더와 애플리케이션 폴더가 명확하게 구분되도록 작업 디렉터리를 설정해야 합니다. 이 경우 /app을 사용합니다.
ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate
이제 프로젝트 종속성 정보가 포함된 파일을 복사하여 설치해야 합니다.
WORKDIR /app
--frozen-lockfile 및 --prefer-frozen-lockfile 인수는 pnpm의 잠금 파일에 지정된 버전을 존중하는 데 사용됩니다.
이 단계를 마무리하기 위해 샤프 라이브러리가 추가됩니다. 이는 Next.js의 프로덕션 환경에서 이미지를 최적화하기 위해 필요합니다.
COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile
전체 무대는 이렇습니다.
RUN pnpm add sharp
다음 단계는 Next.js 애플리케이션을 컴파일하는 것입니다. Dockerfile의 나머지 부분은 다르지 않거나 다른 예제에서 찾을 수 없기 때문에 이미지를 작동시키기 위한 핵심이 여기에 있습니다. 이 단계에서는 프로젝트에 사용된 환경 변수를 빌드 인수로 전달하고 빌드를 생성하기 전에 이를 설정해야 합니다.
애플리케이션이 작동하는 두 가지 시간(빌드 시간과 런타임)이 있기 때문에 환경 변수를 런타임에 사용할 수 없으면 이를 사용하는 모든 정적 자산에 대한 값이 없기 때문입니다. 그리고 응용 프로그램이 제대로 작동하지 않습니다. 이 예에서는 NEXT_PUBLIC_BACKEND_URL, FRONTEND_URL 및 JWT_SECRET의 세 가지 환경 변수가 사용됩니다.
FROM base AS build-deps RUN apk add --no-cache libc6-compat ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile RUN pnpm add sharp
그런 다음 pnpm이 활성화되고 작업 디렉터리가 설정되며 모든 애플리케이션 파일이 복사되고 빌드가 생성됩니다.
FROM base AS builder ARG NEXT_PUBLIC_BACKEND_URL ENV NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL ARG FRONTEND_URL ENV FRONTEND_URL=$FRONTEND_URL ARG JWT_SECRET ENV JWT_SECRET=$JWT_SECRET
전체 무대는 이렇습니다.
RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY --from=build-deps /app/node_modules ./node_modules COPY . . RUN pnpm build
마지막 단계는 애플리케이션을 실행하는 것입니다. 이를 위해 먼저 Node 제작 환경을 설정합니다.
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
개인 취향에 따라 Next.js 원격 측정이 비활성화됩니다. 즉, 기본적으로 우리는 오류 진단 및 사용 지표를 통해 Next.js를 개선하기 위해 애플리케이션 데이터를 Vercel에 보내지 않습니다.
FROM node:22.6.0-alpine3.19 AS base
또한 Docker 이미지에는 루트가 아닌 사용자를 사용하는 것이 좋습니다. 예를 들어 컨테이너가 호스트 네트워크에 액세스할 수 있는 경우 보안 위반을 방지합니다. 이를 위해 nodejs 그룹과 nextjs 사용자가 추가되고 .next 폴더 속성이 할당됩니다.
FROM base AS build-deps RUN apk add --no-cache libc6-compat
그런 다음 독립형 빌드에서 생성된 파일을 복사하여 Next.js의 기본 빌드와 동일한 구조를 만듭니다.
ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate
nextjs 사용자를 생성했으므로 이 사용자를 사용할 사용자로 지정해야 합니다.
WORKDIR /app
마찬가지로 컨테이너의 노출된 포트를 지정해야 하며, 사용할 Node 포트와 호스트 이름도 지정해야 하는데, 정확한 주소를 모르기 때문에 0.0.0.0이 됩니다.
COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile
그런 다음 애플리케이션 런타임에 대한 환경 변수가 빌드 인수에서 지정됩니다.
RUN pnpm add sharp
docker-compose.yml 파일에 지정된 환경 변수를 사용할 수 있을 뿐만 아니라 컨테이너를 실행할 때도 사용할 수 있습니다. 그러나 이 컨텍스트의 환경 변수가 빌드 시간과 런타임에 다르다는 것은 의미가 없습니다. .
드디어 서버를 운영합니다.
FROM base AS build-deps RUN apk add --no-cache libc6-compat ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile RUN pnpm add sharp
전체 Dockerfile은 다음과 같습니다.
FROM base AS builder ARG NEXT_PUBLIC_BACKEND_URL ENV NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL ARG FRONTEND_URL ENV FRONTEND_URL=$FRONTEND_URL ARG JWT_SECRET ENV JWT_SECRET=$JWT_SECRET
본 요지에서도 파일을 찾으실 수 있습니다.
Next.js 애플리케이션용 Docker 이미지를 생성하는 것은 고려해야 할 모든 고려 사항 때문에 처음에는 어려울 수 있습니다. 또한 Next.js 애플리케이션을 자체 호스팅한다는 대중적인 믿음이 있습니다. 즉, Vercel 외부는 복잡합니다. 그렇지 않습니다. 핵심 부분을 이해하면 사실 간단합니다.
이 정보를 사용하여 문제 없이 Next.js 애플리케이션을 도킹할 수 있기를 바랍니다. 질문이 있거나 공유하고 싶은 내용이 있으면 댓글에 남겨주세요 :)
위 내용은 독립 실행형 빌드를 사용하여 Next.js 애플리케이션 Docker화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!