How I Dockerized my Next.js website?
Tags: nextjs, docker, devops, tutorial
Published: 2021-05-08 05:20:22

Learn how to use Docker to create images for development and production.

Imagine that you have developed a full fledged working application and want other developers to contribute to the project. Now if the application consists of different components like UI, running server, database etc. The new developer should install the exact configuration of  the entire stack on to his/her system before starting  the development. To overcome this issue Docker comes to the rescue.

## What is Docker?

Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.

## Multistaging dockerfile for development and production

I created a common docker file for both development and production. Dockerfile is used to create an image of the application, using this image n number of containers can be created, which is like a running version of the image.

🐬**Dockerfile**

```docker
#Creates a layer from node:alpine image.
FROM node:alpine

#Creates directories
RUN mkdir -p /usr/src/app

#Sets an environment variable
ENV PORT 3000

#Sets the working directory for any RUN, CMD, ENTRYPOINT, COPY, and ADD commands
WORKDIR /usr/src/app

#Copy new files or directories into the filesystem of the container
COPY package.json /usr/src/app
COPY package-lock.json /usr/src/app

#Execute commands in a new layer on top of the current image and commit the results
RUN npm install

##Copy new files or directories into the filesystem of the container
COPY . /usr/src/app

#Execute commands in a new layer on top of the current image and commit the results
RUN npm run build

#Informs container runtime that the container listens on the specified network ports at runtime
EXPOSE 3000

#Allows you to configure a container that will run as an executable
ENTRYPOINT ["npm", "run"]
```


## 🐙Docker-Compose to create containers with ease.

Suppose you have an application that consists of UI, running server, DB and you want to create containers for all the components. One way is to create Dockerfile for each of the component and start the containers one by one manually or docker-compose can be used to start the entire stack with just one command.

Below is the common docker-compose.yml file for both development and production

🐬**docker-compose.yml**

```yaml
version: '3' #This denotes that we are using version 3 of Docker Compose
services: #This section defines all the different containers we will create.
  blog_deepak: #This is the name of our Nextjs application.
    build: #This specifies the location of our Dockerfile
      context: . #This specifies the location of our Dockerfile
    ports: #This is used to map the container’s ports to the host machine.
      - "3000:3000"
```

🐬**docker-compose.dev.yml**

```yaml
version: "3" #This denotes that we are using version 3 of Docker Compose
	services: #This section defines all the different containers we will create.
    blog_deepak: #This is the name of our Nextjs application.
        command: dev #command to execute
				#This is just like the -v option for mounting disks in Docker. In this              example, we attach our code files directory to the containers’ ./code              directory.  This way, we won’t have to rebuild the images if changes are           made.
        volumes:
            - .:/usr/src/app
            - /usr/src/app/node_modules
            - /usr/src/app/.next
```

🐬**docker-compose.prod.yml**

```yaml
version: "3" #This denotes that we are using version 3 of Docker Compose
services: #This section defines all the different containers we will create.
    blog_deepak: #This is the name of our Nextjs application.
        command: prod #command to execute
```

I have configured my scripts in package.json to run docker-compose.

**package.json**

```json
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "prod": "next start",
    "dev:up": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up",
    "prod:up": "docker-compose -f docker-compose.yml -f docker-compose.prod.yml up"
  },
```

By default, Compose reads two files, a docker-compose.yml and an optional docker-compose.override.yml file. By convention, the docker-compose.yml contains your base configuration. The override file, as its name implies, can contain configuration overrides for existing services or entirely new services.

To use multiple override files, or an override file with a different name, you can use the -f option to specify the list of files. Compose merges files in the order they’re specified on the command line.