# Day 24: Docker - Deploying Node.js Application with Docker - A Quick Guide

A Dockerfile is a plain text configuration file that contains instructions for building a Docker image. An image is a lightweight, standalone, executable software package that includes everything needed to run a piece of software, including the code, runtime, system tools, libraries, and settings. Docker images are the building blocks of containers, which are instances of images that can be run as isolated environments.

You create a Dockerfile to define the steps and components required to create a specific Docker image. Each instruction in a Dockerfile represents a layer in the image's filesystem. Docker uses these layers to efficiently manage and distribute images.

**When to Create a Dockerfile:**

1. **Custom Application Images:** When you want to package your application along with its dependencies and configurations into a Docker image.
    
2. **Version Control:** Dockerfiles provide a way to version control and reproduce your images, ensuring consistency across different environments.
    
3. **Automated Builds:** Dockerfiles enable automated builds, which are triggered whenever code changes occur, resulting in consistent and up-to-date images.
    
4. **Collaboration:** Sharing Dockerfiles allows others to recreate the same image and environment you've defined.
    
5. **Scalability:** Docker images are portable and can be easily scaled up or down, making them suitable for microservices architectures.
    

Here are some common commands used in a Dockerfile, along with explanations:

Certainly! Let's go through each component of a Dockerfile in detail and provide examples for better understanding:

1. **FROM:** Specifies the base image upon which your Docker image is built.
    
    ```Dockerfile
    FROM ubuntu:20.04
    ```
    
    In this example, we're using the Ubuntu 20.04 base image as the foundation for our Docker image.
    
2. **RUN:** Executes commands in the image's shell during the build process.
    
    ```Dockerfile
    RUN apt-get update && apt-get install -y package-name
    ```
    
    This command updates the package repository and installs a package named `package-name`.
    
3. **COPY:** Copies files and directories from the build context (your local machine) into the image.
    
    ```Dockerfile
    COPY source-destination /app/
    ```
    
    This command copies the contents from the `source-destination` on your local machine into the `/app/` directory within the image.
    
4. **ADD:** Similar to COPY, but with additional features like remote URL support and automatic file extraction.
    
    ```Dockerfile
    ADD https://example.com/file.tar.gz /app/
    ```
    
    This command adds a remote archive to the `/app/` directory within the image and automatically extracts it.
    
5. **WORKDIR:** Sets the working directory for subsequent commands in the Dockerfile.
    
    ```Dockerfile
    WORKDIR /app
    ```
    
    This command sets the working directory to `/app` within the image.
    
6. **ENV:** Sets environment variables in the image.
    
    ```Dockerfile
    ENV PORT=8080
    ```
    
    This command sets an environment variable `PORT` with the value `8080`.
    
7. **EXPOSE:** Specifies which ports the container will listen on at runtime.
    
    ```Dockerfile
    EXPOSE 80/tcp
    ```
    
    This command exposes port 80 within the container for network communication.
    
8. **CMD:** Provides the default command to run when a container starts.
    
    ```Dockerfile
    CMD ["npm", "start"]
    ```
    
    This command sets the default command to run when the container starts: `npm start`.
    
9. **ENTRYPOINT:** Similar to CMD, the command and arguments are not overridden when running the container with additional arguments.
    
    ```Dockerfile
    ENTRYPOINT ["node", "app.js"]
    ```
    
    This command specifies the entry point command and arguments.
    
10. **VOLUME:** Creates a mount point as a volume.
    
    ```Dockerfile
    VOLUME /data
    ```
    
    This command creates a volume at `/data` within the container.
    
11. **USER:** Sets the user or UID for the subsequent commands in the Dockerfile.
    
    ```Dockerfile
    USER appuser
    ```
    
    This command switches the user to `appuser` for the following commands.
    
12. **ARG:** Defines build-time variables that can be used in the Dockerfile.
    
    ```Dockerfile
    ARG VERSION=latest
    ```
    
    This command sets an argument `VERSION` with a default value of `latest`.
    
13. **LABEL:** Adds metadata to the image in key-value pairs.
    
    ```Dockerfile
    LABEL maintainer="user@example.com"
    ```
    
    This command adds a label indicating the maintainer's email to the image.
    
14. **ONBUILD:** Executes instructions when the image is used as a base image for another build.
    
    ```Dockerfile
    ONBUILD COPY . /app
    ```
    
    This command copies the build context to `/app` when the image is used as a base.
    

Each component in a Dockerfile serves a specific purpose and contributes to building a self-contained and reproducible Docker image for your application. By combining these components effectively, you can define the entire process of setting up, configuring, and running your application within a container.

**A step-by-step guide to deploying a Node.js application using a Dockerfile:**

Assumptions:

1. You have a working Node.js application with an "app.js" file that creates a simple Express.js server.
    
2. Your application listens on port 3000.
    

Step 1: Set up the project directory and files

Create a new directory for your Node.js application and navigate to it:

```bash
mkdir my_node_app
cd my_node_app
```

Create an "app.js" file with the following code:

```javascript
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World, Welcome to TechWithAnkush WebPage');
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});
```

Step 2: Initialize the Node.js application and install dependencies

Initialize the Node.js project and create a "package.json" file:

```bash
npm init -y
```

Install Express.js, a popular web framework for Node.js:

```bash
npm install express
```

Step 3: Test the application

You can test your application without Docker by running it directly using Node.js:

```bash
node app.js
```

Your Node.js application should now be running, and you can access it at [http://localhost:3000](http://localhost:3000), where you should see the "Hello, World!" message.

Step 4: Create the Dockerfile

Create a new file named "Dockerfile" (without any file extensions) in the root directory of your Node.js application.

Open the Dockerfile in a text editor and add the following content:

```Dockerfile
# Use an official Node.js runtime as a base image
FROM node:14

# Set the working directory inside the container
WORKDIR /app

# Copy the package.json and package-lock.json files into the container
COPY package*.json ./

# Install application dependencies
RUN npm install

# Copy the rest of the application code into the container
COPY . .

# Expose the port on which the Node.js app runs
EXPOSE 3000

# Define the command to start your Node.js application
CMD ["node", "app.js"]
```

Save the Dockerfile.

Step 5: Build the Docker image

Open a terminal or command prompt and navigate to the directory containing the Dockerfile and your Node.js application files.

Build the Docker image using the following command. Replace "my-node-app" with the desired image name, and the period "." specifies the current directory as the build context:

```bash
docker build -t node:v1 .
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1691425308365/77b58be2-b094-4404-9515-f5a276d34917.png align="center")

Step 6: Run the Docker container

Once the image is built, you can run the container from the image using the following command:

```bash
docker run -p 3000:3000 node:v1
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1691425351194/bcd5c8b6-e813-4f27-8da1-05bebde82ece.png align="center")

Your Node.js application is now running inside a Docker container, and you can access it at [http://localhost:3000](http://localhost:3000), just like before.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1691425367530/8c7b3424-7dfb-4c18-89e1-20bb44633c9b.png align="center")

That's it! You've successfully deployed a Node.js application using Docker. Now you can share the Docker image with others or deploy it to a container orchestration platform like Kubernetes for scalable deployments.

Thanks for reading! I hope you found this blog informative and insightful. For more technology-related content, don't forget to follow me on [GitHub](https://github.com/techwithankush) and [LinkedIn](https://www.linkedin.com/in/techwithankush)
