Next.js and Docker
In this blog post I’m introducing a dangerously good application development duo, Next.js and Docker. To start, I’ll briefly go over both Next.js and Docker. After, I’ll explain how you can combine these two technologies. Let’s get this party
Next.js is an open-source React framework built on top of Node.js. Next.js leverages a wide array of functionalities such as hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. In fact, This website was built using Next.js!
Curious about giving it a try? Next.js has a step-by-step tutorial on building your first app. To get a Next.js app up and running in seconds you can use
npx create-next-app@latest or
yarn create next-app. Also, if you get stuck you can visit the Create Next App documentation. There are even official Next.js templates you can snag.
Docker is an open platform for developing, shipping, and running apps. Before Docker, you had to locally set up your app and all of its dependencies according to your machine. Docker eliminates this issue by packaging and running apps in loosely isolated environments called containers.
Docker also has a great overview on their website.
Docker Command Starter Kit
Here are the most useful commands I found to get you up and running with Docker. For more detailed information on each command and all other commands you can visit Docker’s documentation.
docker login- log in to local registry or Docker Hub
docker pull IMAGE- pulls an image from Docker Hub (default registry), but you can specify a different one
docker push IMAGE- pushes an image to Docker Hub (default registry), but you can specify different one
docker images- gives you a list of images on the host machine
docker run IMAGE- creates a Docker container of the specified Docker image and starts it in the current terminal
docker stop CONTAINER- stops a given container
docker start CONTAINER- starts a given container
docker ps- status of all running containers
docker ps -a- status of all running and not running containers
docker logs CONTAINER- gives the logs of a given container
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]- runs a command in a running container
docker network ls- see all available Docker networks
docker network create example-network- creates a network
docker build -t IMAGE:tag dockerfile-location- builds an image from the specified Dockerfile and will then tag it
docker rm CONTAINER- deletes a container
docker rmi image- deletes an image
docker version- provides docker version information
Next.js and Docker
Let’s say you’ve crafted yourself a performant, stunning, and interactive Next.js application.
Once you create a Dockerfile for your Next.js application, you can use it to create a Docker image and then a Docker container. To create an image, we use
docker build and then to create a container we use
docker run. Take for example this Dockerfile I use to create an image of this website which should apply to most Next.js apps:
# Building image # docker build . -t example-image-name # Install dependencies only when needed FROM node:14-alpine 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 COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Rebuild the source code only when needed FROM node:14-alpine AS builder WORKDIR /app COPY . . COPY --from=deps /app/node_modules ./node_modules RUN yarn build # Production image, copy all the files and run next FROM node:14-alpine AS runner WORKDIR /app ENV NODE_ENV production RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 # You only need to copy next.config.js if you are NOT using the default configuration # COPY --from=builder /app/next.config.js ./ COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json USER nextjs EXPOSE 3000 ENV PORT 3000 # 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. # ENV NEXT_TELEMETRY_DISABLED 1 CMD ["node_modules/.bin/next", "start"]
You can see how the Dockerfile’s instructions create layers to form the resulting image.
Consider this set of instructions where each instruction creates one layer:
FROMcreates a layer from the
RUNadds missing shared libraries to our image
WORKDIRsets the working directory for any subsequent instructions
COPYadds our dependency blueprints (package.json/yarn.lock) from the Docker client’s current directory
RUNinstalls all of our Next.js application’s dependencies with yarn
Let’s use this Dockerfile to get our Next.js app running on a container. Place the Dockerfile in the outermost directory of your Next.js application. Now, we can run
docker build . -t example-image-name in that outermost directory of the Next.js application to forge an image! Finally with the command
docker run -p3000:3000 example-image-name you can create a container. After using the
docker run command you can actually view your app running on the container. With your image and container you are poised to deploy to any Docker hosting platform.
To summarize, we’ve learned about what Next.js and Docker are and how you can use them together. Next.js is a leading frontend framework with a phenomenal developer experience. Docker is an open platform for development and ops best practices. Docker also has collaboration features such as
docker push and
docker pull to run images on any machine. If you’re looking to share and deploy beautiful frontend applications, these two technologies definitely are the life of the party.