Goglides Dev 🌱

Nitish Kafle
Nitish Kafle

Posted on • Originally published at dev.to on

Dockerizing your Next.js/React Application!

What is Docker?

Docker is a software framework for building, running, and managing containers on servers and the cloud. Think of Docker as a CLI but for the cloud.

For this tutorial, we will be using Next.js sample application and create a Dockerfile in order to Dockerize it.

Requirements:

In order to complete Dockerizing your Next.js app, you will need the following:

  • Docker installed on your computer.
  • Node.js and npm/yarn installed on your system in order to create Next app.

Creating a sample Next.js app

If you already have an application that you want to dockerize then, you can proceed with further steps else let’s create a next.js app.

Run the following command on your terminal:

yarn create next-app 

Enter fullscreen mode Exit fullscreen mode

This command will initialize files and configurations that are required to create and run your next.js application.

Creating a Dockerfile

First, let’s open our app in VS Code or any Code Editor of your choice.

Run the following commands:

cd <your app name>


code . 

Enter fullscreen mode Exit fullscreen mode

(assuming you have vscode configured)

Here, you will see the directories of your application. That would look something similar like this.

[Note: I am using TypeScript that’s why you are seeing tsconfig.json and files that ends with .ts]

file contents

Go ahead and create a new file and name it Dockerfile. By default, this file is recognized by docker and it will executes bunch of commands and instructions that we will provide.

Remember: The commands will be executed in order of how they are written.

Inside the Dockerfile write these codes. I will go through each one and explain how it works at the end of the tutorial.

[Note: I am using yarn for this tutorial, you can use npm but you will have to swap those yarn executable code with npm]

FROM node:lts as dependencies
WORKDIR /<your-app-name>
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

FROM node:lts as builder
WORKDIR /<your-app-name>
COPY . .
COPY --from=dependencies /<your-app-name>/node_modules ./node_modules
RUN yarn build

FROM node:lts as runner
WORKDIR /<your-app-name>
ENV NODE_ENV production

COPY --from=builder /<your-app-name>/public ./public
COPY --from=builder /<your-app-name>/package.json ./package.json
COPY --from=builder /<your-app-name>/.next ./.next
COPY --from=builder /<your-app-name>/node_modules ./node_modules

EXPOSE 3000
CMD ["yarn", "start"]

Enter fullscreen mode Exit fullscreen mode

Building Docker Image

Execute the following command to build the Docker image.

docker build . -t <project-name>

Enter fullscreen mode Exit fullscreen mode

This command will build the Docker image with the name <project-name>.

Running the Docker image once the build is over with the following command.

docker run -p 3000:3000 <project-name>

Enter fullscreen mode Exit fullscreen mode

Now, open the browser and navigate to

http://localhost:3000 

Enter fullscreen mode Exit fullscreen mode

to view your project.

CONGRATULATIONS! You have successfully dockerized your application!

Congrats

Visiting contents of the Dockerfile

Now, let’s go through the code contents of the Dockerfile.

Remember, the code are executed based on how they are written, top-down approach.

Lets go through the code in three different stages in top-down approach:

  1. Installing dependencies
  2. Building our Next.js application
  3. Configuring the runtime environment for our application

1. Installing Dependencies

FROM node:lts as dependencies
WORKDIR /<your-app-name>
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

Enter fullscreen mode Exit fullscreen mode

Let’s talk about what is happening on this code.

First, we want to define what image we want to build from for which we are using the latest node version with node:lts

You could use any specific version of node. For example: FROM node:16 would build your image with Node version 16. We are using as dependencies so that we can export this code and reuse it later when building our application in docker.

Second, we want to create an application directory which holds our application code with WORKDIR.

Third, we want to copy our package.json and yarn.lock files which allows us to take advantage of cached Docker layers. A good explanation of Docker Caching is here.

Finally, we want to be able to run our yarn install to install these dependencies. We are using --frozen-lockfile because our yarn.lock or package-lock.json gets updated when running yarn install ( or npm install). We do not want to check for these changes.

If you are using npm you can use npm ci (ci means clean install / use it for production or else just use RUN npm install)

For yarn its --frozen-lockfile

2. Building our Next.js application

FROM node:lts as builder
WORKDIR /<your-app-name>
COPY --from=dependencies /<your-app-name>/node_modules ./node_modules
RUN yarn build

Enter fullscreen mode Exit fullscreen mode

Let’s look at the build.

Here, we build our application copying dependencies from node_modules.

If you are using npm then use RUN npm build.

FROM node:lts as runner
WORKDIR /<your-app-name>
ENV NODE_ENV production

Enter fullscreen mode Exit fullscreen mode

After building our project, we want to be able to run it.

3. Configuring the runtime environment for our application

COPY --from=builder /<your-app-name>/public ./public
COPY --from=builder /<your-app-name>/package.json ./package.json
COPY --from=builder /<your-app-name>/.next ./.next
COPY --from=builder /<your-app-name>/node_modules ./node_modules

EXPOSE 3000
CMD ["yarn", "start"]

Enter fullscreen mode Exit fullscreen mode

Here, we want to be able to bundle the app source code inside our Docker image that’s why we are using COPY.

Finally, we want to define a command to run our app using CMD which defines the runtime.

For our runtime, we are using yarn command.

If you have Docker Application installed, you can view your container on the dashboard and run it from there which would look something like the images below.

Docker Dashboard

Docker Dashboard

You did it!

Thanks for reading. If you have any questions, feel free to send them my way on Twitter @developernit

Top comments (2)

Collapse
 
bkpandey profile image
Balkrishna Pandey

@nitishkafle I like the article; is the TypeScript source accessible on github? Or is it something private you'd prefer not to share?

Collapse
 
nitishkafle profile image
Nitish Kafle

Good point, i should have hosted the starter files / finished version along with the article! will do that in future posts!