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
andnpm/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
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 .
(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
]
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"]
Building Docker Image
Execute the following command to build the Docker
image.
docker build . -t <project-name>
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>
Now, open the browser and navigate to
http://localhost:3000
to view your project.
CONGRATULATIONS! You have successfully dockerized your application!
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:
- Installing dependencies
- Building our
Next.js
application - 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
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
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
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"]
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.
You did it!
Thanks for reading. If you have any questions, feel free to send them my way on Twitter @developernit
Top comments (2)
@nitishkafle I like the article; is the TypeScript source accessible on github? Or is it something private you'd prefer not to share?
Good point, i should have hosted the starter files / finished version along with the article! will do that in future posts!