To deploy our application with Docker, we will need to write a Dockerfile
which in turn is used to create a Docker-Image.
This Image can then be used to deploy our application on any container platform like Docker, Podman or even Kubernetes.
Creating the Dockerfile
Inside the root of our Nextjs App (next to the package.json
) we need to create a file named Dockerfile
.
We will start with a base image. For Example node:20
FROM node:20
Next we will define our working directory and copy our files into there. If you have any secrets, that you don’t want to copy, you should split the Copy-Command into different steps.
FROM node:20
WORKDIR /app
COPY . .
After that we need to define our environment variables. Since NextJS compiles it’s code at build time, we need to provide them now. If you provide them once you start the container, they will be undefined.
To define environment variables we have to options:
- write them directly into the Dockerfile. Do not use this for secrets
- or use build arguments to keep your secrets out of your Dockerfile
FROM node:20
WORKDIR /app
COPY . .
# public variables
ENV NEXT_PUBLIC_BASE_URL=https://jrehkemper.de
# private variables
ARG PG_PASSWORD
ENV PG_PASSWORD=$PG_PASSWORD
The next step is to install our dependencies and build our application.
FROM node:20
WORKDIR /app
COPY . .
# public variables
ENV NEXT_PUBLIC_BASE_URL=https://jrehkemper.de
# private variables
ARG PG_PASSWORD
ENV PG_PASSWORD=$PG_PASSWORD
RUN npm install
RUN npm run build
The last step would be to provide the start command. This command is executed once you start the container.
FROM node:20
WORKDIR /app
COPY . .
# public variables
ENV NEXT_PUBLIC_BASE_URL=https://jrehkemper.de
# private variables
ARG PG_PASSWORD
ENV PG_PASSWORD=$PG_PASSWORD
RUN npm install
RUN npm run build
CMD ["npm", "run", "start"]
Building the Image
Now that we have our recipe (Dockerfile) we can build the image.
$ docker build -t myregistry.example.com/my-repo/my-app:latest .
If you used Build-Args, you need to provide them.
$ docker build -t myregistry.example.com/my-repo/my-app:latest --build-arg PG_PASSWORD=password123 .
If you want to use the image on the different machine as well, you will need to push your image into the specified registry.
$ docker push myregistry.example.com/my-repo/my-app:latest
Multi-Stage Build
You will see that this image is quite big. That’s mostly since it has all the node_modules, the raw source-code and the compiled webapp inside. But usually you only want the compiled webapp.
Multi-Stage builds allow you to do that. You will use a first stage to build your software and a second stage to build the container with only the compiled software.
You can find an Example of this here.