Skip to content

6. Docker

Maruf Bepary edited this page Jun 28, 2023 · 1 revision

This repository comes with Docker configuration files to enable you to build and run the Next.js application in a Docker container, a lightweight, stand-alone, and executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and config files.

Repository Structure

The Docker related files are located within the docker directory at the root of the repository. The docker directory has the following structure:

docker/
├── docker-compose.yml
└── next/
    └── Dockerfile
  • docker-compose.yml: Docker Compose file for orchestrating multi-container Docker applications.
  • next/Dockerfile: Dockerfile for the Next.js application.

Docker Compose File (docker-compose.yml)

Docker Compose is a tool that allows us to define and manage multi-container Docker applications. It uses YAML files to configure the application's services and performs the creation and start-up process of all the containers with a single command.

In this project, the docker-compose.yml file is configured to run the Next.js application.

Here is a breakdown of what each part does:

version: '3'                     # The version of Docker Compose to use
services:                        # Define the services that should be created
  nextjs:                        # The name of the first service
    build:                       # Specifies the options that Docker should use when building the Docker image
      context: ..                # The build context specifies the location of your source files
      dockerfile: docker/next/Dockerfile  # The name and location of the Dockerfile 
    ports:                       # Expose ports
      - 3000:3000               # Maps the internal Docker host port 3000 to the external Docker client port 3000

By using this docker-compose.yml, you can bring up your entire app by using the command docker-compose up and bring it down using docker-compose down from the directory that contains the docker-compose.yml file. This will take care of all the intricacies of setting up the Next.js service.

Services

Dockerfile for Next.js Application (next/Dockerfile)

This Dockerfile utilizes a multi-stage build process. In a multi-stage build, you use multiple FROM statements in your Dockerfile. Each FROM statement can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.

Multi-stage builds are useful to anyone who has struggled to optimize Dockerfiles while keeping them easy to read and maintain.

Breakdown of the Dockerfile

Below is a line-by-line explanation of each part of the Dockerfile.

# ---- Build Stage ----
FROM node:18.16.0-alpine AS builder

This is the first stage of the multi-stage build. It uses the node:18.16.0-alpine Docker image as the base image. This image includes Node.js based on the 18.16.0 version and uses Alpine, a lightweight Docker image. The stage is named builder.

WORKDIR /app

Set the working directory to /app. All the instructions that follow in the Dockerfile will be run from this directory.

COPY package*.json ./

Copy the package.json and package-lock.json (if available) from your host to your image filesystem.

RUN npm install

Run the npm install command inside your image filesystem which installs the dependencies described in package.json.

COPY . .

Copy everything from the current directory in your host to the WORKDIR in your image filesystem.

RUN npm run build

This step will create an optimized production build of your Next.js application.

# ---- Release Stage ----
FROM node:18.16.0-alpine AS release

This begins the second stage of the multi-stage build, also using node:18.16.0-alpine as the base image, named as release.

WORKDIR /app

Sets the working directory to /app.

COPY --from=builder /app/package*.json ./

This copies the package.json and package-lock.json (if available) from the builder stage to the current stage.

RUN npm install --only=production

This will install only the dependencies needed for running the application, and not the devDependencies, thus creating a leaner image.

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public

These lines are copying the built Next.js app files and the public files from the builder stage into the release stage.

EXPOSE 3000

This informs Docker that the container listens on the specified network ports at runtime. In this case, it's port 3000.

CMD ["npm", "start"]

Provides defaults for executing a container, which includes the specifications of what executable to run when the container starts.

In conclusion, this Dockerfile leverages the multi-stage build feature to create a lean, production-ready Docker image of your Next.js application. You start with a larger image containing everything needed to build your application, and then copy just the built application and its runtime dependencies into a smaller, final image.