Building a Docker Image for Node Applications

Introduction

Docker is a platform that simplifies application deployment by packaging it and its dependencies into a container. This guide will walk you through the process of deploying a Node.js application using Docker, focusing on creating a Docker image, using a Dockerfile, and optimizing the Docker setup.

1. Building a Docker Image

A Docker image contains all the files and dependencies needed to run your Node.js application. It acts as a blueprint for creating Docker containers.

1.1. Creating a Dockerfile

A Dockerfile is a script that contains a series of instructions on how to build a Docker image. Here’s how to create one:

  1. Set the Base Image: Start by specifying a base image. Docker Hub offers pre-built images such as Node.js, which you can use as a starting point.

     FROM node:alpine
    
     or
    
     FROM node:16-alpine
    
     or
    
     FROM node:lts-alpine
    
    • The alpine variant is chosen for its small size.
  2. Set the Working Directory: Define where your application files will be located within the container.

     WORKDIR /app
    
  3. Copy Application Files: Copy the necessary files from your local machine to the Docker image.

     COPY . .
    
  4. Install Dependencies: Install the necessary Node.js dependencies.

     RUN npm install --only=production
    
     or
    
     RUN npm run install-server --omit=dev
    
  5. Heads up! Starting from NPM 8, the flag to install only production dependencies changed. Instead of specifying which dependencies to install:

    --only=production

    We now specify which dependencies to omit:

    --omit=dev

    If we're using the latest version of NPM, we'll want to use this new approach each time we run npm install in our Dockerfile. For example, we want to use:

    RUN npm run install-server --omit=dev

    Rather than:

    RUN npm run install-server --only=production

  6. Build the Application: For applications with a front-end, ensure it’s built before serving.

     RUN npm run build --prefix client
    
  7. Set the Startup Command: Define the command that will be executed when the container starts.

     CMD ["npm", "start", "--prefix", "server"]
    

2. Optimizing the Dockerfile

To make your Docker image more efficient and secure:

2.1. Exclude Unnecessary Files

Use a .dockerignore file to exclude files and directories that shouldn't be copied into the image:

node_modules
.git
server/public

2.2. Use Layers

Docker caches each instruction in a Dockerfile as a layer. If an instruction changes, Docker will only rebuild that layer and the ones following it, speeding up the build process.

2.3. Run as Non-Root User

For security, avoid running your application as the root user. Use a non-root user provided by the Node.js base image:

USER node

3. Exposing Ports

Expose the port your application will run on to allow external access:

EXPOSE 8000

Complete Dockerfile

Sharing here complete Dockerfile for my dummy project

FROM node:16-alpine

WORKDIR /app

COPY . .

RUN npm install --omit=dev

USER node

CMD [ "npm", "start" ]

EXPOSE 5000

4. Building and Running the Docker Image

Once the Dockerfile is complete, you can build and run the Docker image:

4.1. Build the Image

Run the following command to build the image:

docker build -t my-node-app .

4.2. Run the Container

Start a container from the image:

docker run -p 5000:5000 my-node-app

4.3. Want to connect .env files like below

Start a container from the image with env:

docker run --env-file .env -p 5000:5000 my-node-app2

5. Additional Best Practices

5.1. Multi-Stage Builds

For more complex projects, consider using multi-stage builds to keep the final image size small by only including necessary files and dependencies.

5.2. Regular Updates

Keep your Docker base images updated to ensure you're using the latest security patches.

5.3. Use Environment Variables

Use environment variables to configure your application dynamically, which is especially useful for different environments like development, staging, and production.


By following this guide, you will be able to deploy Node.js applications using Docker efficiently and securely. This process streamlines deployment, ensures consistency across environments, and simplifies scaling and maintenance.