I wrote about how to use nextjs with docker.
I wanted to compare using next
standalone like in the article and just using
I describe the new docker file I used for using
next start in docker at the bottom of this article. But let's jump straight to the learnings.
Docker Image Size
The standalone mode I used in my original article creates a docker container of 230MB.
next start mode creates a docker container of 750MB.
If you're passing around many docker containers throughout the day the lower size of standalone mode can be a big difference.
Static Asset serving
Standalone next build provides you a separate set of static assets that you can use in AWS S3 or similar instead of your docker container.
This is a big advantage of standalone mode if you have many static assets or your site is very busy.
next start method is easier to setup in docker. It's also the default way to run nextjs and will always support all next features.
The standalone method is a bit more complex to setup in docker but once you set it up it doesn't change very often.
The standalone image is less than half the size of the full app method.
I'm going to continue using standalone for now!
Appendix: The next start dockerfile used
To setup the test we use the following dockerfile:
# A container with pnpm and python3 is required FROM node:18-alpine as pnpm_base WORKDIR /app RUN npm i --global --no-update-notifier --no-fund pnpm@7 RUN apk add --no-cache g++ make py3-pip libc6-compat # run fetch in a separate step to avoid re-fetching deps on every change FROM pnpm_base as fetched_deps WORKDIR /app ENV NODE_ENV production COPY pnpm-lock.yaml ./ RUN pnpm config set store-dir /workdir/.pnpm-store RUN pnpm fetch # install all deps from cache FROM fetched_deps as with_all_deps COPY . ./ RUN pnpm install --offline # Build the BE # the main issue with building everything is the FE depends on a running BE FROM with_all_deps as builder RUN pnpm --filter='*frontend' build RUN pnpm --filter='*frontend' deploy pruned --prod # Production image - only take pruned assets FROM node:18-alpine AS runner WORKDIR /app ENV NODE_ENV=production RUN addgroup --system --gid 1001 app RUN adduser --system --uid 1001 app USER app COPY /app/apps/frontend/ / EXPOSE 5000 ENV PORT 5000 CMD ["npm", "start"]
Here is another example using yarn
FROM node:18-alpine as base FROM base as with_all_deps WORKDIR /app COPY . ./ RUN yarn RUN yarn build RUN yarn cache clean --all FROM node:18-alpine AS runner WORKDIR /app ENV NODE_ENV=production RUN addgroup --system --gid 1001 app RUN adduser --system --uid 1001 app USER app COPY /app ./ EXPOSE 5000 ENV PORT 5000 CMD ["yarn", "start"]