2024. 1. 4. 16:45ㆍdocker
새롭게 프로젝트 시작하기 전에 가볍게 Nextjs 14.0.4 환경에서 빌드한 파일을 용량 최적화와 함께 Docker로 한번 배포해보자
사실 vercel 에서 제공하는 Dockerfile 과 docker-compose 를 거의 복사 붙여넣기에 가까운 글이니
https://github.com/vercel/next.js/tree/canary/examples/with-docker-compose
직접가서 뜯어보시며 보는것도 나쁘지 않다고 생각함
시작은 craete-next-app 아무것도 안건들꺼다
프로젝트 최상단 경로에 Dockerfile 생성
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN npm ci
FROM base AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build
# If using npm comment out above and use below instead
# RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
CMD ["node", "server.js"]
짧게 설명하면 node 18 alpine 환경에
npm을 사용했고
개발환경 dev
프로젝트 빌드에 builder
빌드 프로젝트 실행에 runner 를 사용했다.
다음은 compose
services:
frontend-prod:
container_name: frontend-prod
build: .
restart: always #change if you don't want your container restarting
environment:
- NODE_ENV=production
ports:
- 3000:3000
frontend-dev:
container_name: frontend-dev
build:
context: . #if your Dockerfile is not at the same level change the path here (./frontend)
target: dev
restart: always
command: npm run dev
environment:
- NODE_ENV=development
volumes:
- .:/app
- /app/node_modules
- /app/.next
ports:
- 3000:3000
근데 어쩌다보니 적용하긴 했지만 개발환경까지 굳이 도커위에 올려줘야하나 싶긴 했다.
( 개발환경이랑 배포환경 두개 동시에 켤 일이 있나 싶어서 ports 는 같게 해줬는데 불편하면 package.json 가서 포트 변경 하자 )
대충 요약해서 설명하면 frontend-dev 는 파일 통째로 싹 복사해서 docker에 올려버리는거
frontend-prod 는 nextjs 로 빌드한 폴더만 가지고 최적화 시켜서 올려버리는거
뭐 프로젝트 커지면 Dockerfile 이랑 Docker-compose 도 다 따로 만드는 것 같은데 ( vercel 에서 제공하는 예시코드 보면 그렇게 되어있더라 ) 그건 프로젝트 커지면 그때 바꿔도 늦지 않을듯..?
올려놓고 보면 용량차이가 꽤 심하다.
파일두개 만들었으면 실행시켜보자
docker compose -f docker-compose.prod.yml up frontend-prod
docker compose -f docker-compose.prod.yml up frontend-dev


다 만들어졌으면 localhost:3000 에 프로젝트가 뜬다.
그런데 배포버전이야 빌드해서 한번 올려놓으면 되지만
저 환경에서 개발을 하려면 react 의 hot reload 기능이 있어야 하지 않겠음?
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,
aggregateTimeout: 300,
};
return config;
},
};
module.exports = nextConfig;
이렇게 해주면 잘됨.
output standalone 은 최적화랑 관련있는데 배포할때 필요없는 코드 지워줌
참고
https://jameschambers.co.uk/nextjs-hot-reload-docker-development
https://tech.inflab.com/20230918-rallit-standalone/
https://github.com/vercel/next.js/tree/canary/examples/with-docker-compose
'docker' 카테고리의 다른 글
| Docker 기본 개념 (1) | 2024.01.04 |
|---|