This post will focus on the way to dockerize a NextJS application. Here, we will see how to use multi-stage docker to optimize the final docker image.
Setup
The first step is to create a Dockerfile
file into your project directory. The goal here is to build and create
a multi-stage image to being able to build an optimized Docker image. Each stage will be built in separate layer
so each layer will be lightweight.
FROM node:lts-alpine as dependencies
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
FROM node:lts-alpine as builder
WORKDIR /app
COPY . .
COPY --from=dependencies /app/node_modules ./node_modules
RUN yarn build
FROM node:lts-alpine as runner
ARG APP=/app
ENV APP_USER=runner
RUN addgroup -S $APP_USER \
&& adduser -S $APP_USER -G $APP_USER \
&& mkdir -p ${APP}
RUN chown -R $APP_USER:$APP_USER ${APP}
WORKDIR /app
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
We are setting a custom user
runner
for security.
Ignore unwanted files
The .dockerignore
file will act as .gitignore
, It uses a different pattern, each match will be excluded from the
docker image when building It.
# add git-ignore syntax here of things you don't want copied into docker image
.git
*Dockerfile*
node_modules
.env
Compose
The docker-compose.yaml
will then be used for development purpose as we may rely on Kubernetes for deployment.
You will need to adapt
image:
value.
services:
app:
image: ghcr.io/my-github-username/my-blog-name
build:
context: .
dockerfile: Dockerfile
ports:
- 3000:3000
command: ["yarn", "dev"]
environment:
- "NODE_ENV=development"
stdin_open: true
tty: true
volumes:
- .:/app
- /app/node_modules
- /app/.next
Using It
Now you can just launch your application in development
mode by running docker-compose up
Production
- You will need to adapt
NODE_ENV
environment variable toproduction
- The command for running the container will be
["yarn", "start"]