Introduction
Node.js is a powerful JavaScript framework for creating web applications, while Docker is an excellent solution for packing and deploying software. Combining these two technologies helps create a scalable and consistent environment to streamline web application deployment.
This article will show how to build a Node.js app with Docker.

Prerequisites
- A system running Ubuntu (the guide uses Ubuntu 24.04).
- Access to an administrator account.
- Docker installed.
- Node.js and npm installed.
- A Docker Hub account.
Step 1: Create a Project and Install Dependencies
To create an image, start by making the Node.js project directory and installing dependencies:
1. Create a directory and enter the location using the cd command:
The my_project
directory is the root directory of the Node.js application. If you use a different name, adjust it in all subsequent commands.
2. Create a package.json file using an editor such as nano:
The file provides a simple way to manage Node.js dependencies and project information.
3. Add this code to the file:
The file now has the following data:
name
. The project name that gets published to the npm Registry. Use a short, descriptive, and unique name.version
. The project's version number.description
. A short description of the project.author
. The project creator.license
. Set to MIT to allow free use and distribution. Adjust to a different license if necessary.main
. Defines the project's entry point (an app.js file).keywords
. The project's keywords, which npm indexes.dependencies
. Lists the dependent package (express
) and version.
4. Save the package.json file and close nano (CTRL+X, Y, Enter).
5. Install the project's dependencies with:
The command installs the packages listed in the dependencies
field in the package.json file.
Step 2: Create App Structure
This step creates a simple web application that provides information on phoenixNAP's Bare Metal Cloud (BMC) servers. The project directory consists of the following files:
- app.js file. The main entry point that contains all project routes.
- views directory. Contains the following static pages for the web application:
- index.html file. The landing page with simple information about BMC servers, which links to a more detailed page.
- bmc.html file. The detailed page with additional information.
Follow the instructions below to create the application structure.
Create Routes and Mount Assets
The following steps create the project routes and mount the project assets. Routing allows linking requests to the correct paths and corresponding pages.
1. In the project directory (~/my_project), create the main entry point file:
2. Define the project constants. Add the following code to the app.js file:
The code does the following:
- Line 1 loads the Express module, which the following two lines use to create backend objects.
- Lines 2-3 create the Express
app
object, which gives access to create a Router object. The Router object helps define HTTP method routes and how the app handles requests. - Line 4 defines the default path for the project's pages as ~/my_project/views/.
- Line 5 sets the default listening and bind port as
8080
.
Keep the file open and proceed to the next step.
3. Add the project routes with the following code:
The code contains three router functions:
router.use
is a middleware function that logs requests and forwards them to the app routes.router.get
defines two app routes as GET requests. The first defines the default route and links it to theindex.html
page, whereas the second defines the/bmc
route and links to thebmc.html
page.
4. Mount the assets and define the application launch:
The application listens on port 8080 when launched.
5. The completed app.js file looks like the following:
6. Save the file and close the editor.
Create Static Pages
The following steps provide a guideline and templates to create the index.html and bmc.html static pages:
1. Create a views directory inside the project root:
2. Create the landing page (index.html):
3. Add the following code to the file:
The code contains several Bootstrap elements to create a sample responsive page. The navbar sets the home page as active and links to the current page and the /bmc
route. An additional button on the page links to the /bmc
page, too.
The code also contains a linked CSS stylesheet (styles.css).
4. Save the file and close the editor.
5. Create the bmc.html file with:
6. Add the following code to the file:
The navbar changes the active page to BMC and links other navigation bar elements to the home page.
7. Save and close the file.
8. Create a separate directory for the CSS file:
9. Make the styles.css file:
10. Add the following code to the file:
11. Save the file and close nano.
Step 3: Run the Application
All files and dependencies for the project are ready. To run the application:
1. Enable traffic on port 8080. For example, if you use UFW, run:
2. Run the server with:
The terminal shows the server is ready and listening on port 8080.
3. Open a browser and access the page via localhost:
The link opens the landing page.
4. Click the button or second BMC page in the navigation bar to access the bmc.html page.
5. The terminal shows these requests. To quit the server, press CTRL+C in the terminal to terminate the session.
Step 4: Create Dockerfile
A Dockerfile is a script file that provides instructions on how to create a Docker image. Create a Dockerfile to specify which pages to include in the application container and define the project's dependencies.
Follow the steps below:
1. Create the Dockerfile:
2. Add the build steps to the file:
Each line does the following:
FROM
. Creates an official Docker image which is based on Alpine Linux. The distribution base image has a minimal size, which helps keep the Docker image size minimal.RUN
. Creates directories for managing app permissions and changes the ownership of these directories to the node user. Leaving ownership to the root user is not recommended.WORKDIR
. Sets the working directory for the app as /home/node/app.COPY
. Copies the package.json file (and package-lock.json for npm 5 and greater). Docker's caching mechanism enables rebuilding only when the files update with new changes.USER
. Switches to the node user.RUN
. Runs thenpm install
command.COPY
. Changes the ownership of the code files to the node user.EXPOSE
. Exposes port 8080 on the container.CMD
. Runs thenode app.js
command and starts the application.
3. Save the file and close nano.
4. Create an ignore file:
The ignore file specifies the files and directories that should not be added to the container.
5. Add the following list to the file:
If using Git, add the .git directory and .gitignore files to the list.
Step 5: Build an Image and Run Container
The files are ready to build a Docker image from the Dockerfile and to create a container from the image. Run the Docker commands below to complete the process:
1. Build the image with the docker build command:
Add your Docker Hub username to the command.
2. Run the following command to see the built docker image:
The output lists the created Docker image.
3. Create the container with the docker run command:
4. List the container details and fetch the address from the output:
The PORTS section from the output shows the server address and port.
5. Access the address through a browser to view the containerized image.
Step 6: Publish to Docker Hub
Publishing the image to a Docker Hub repository makes the project available for further development and subsequent use. To publish the project to the Docker Hub, do the following:
1. Log into your Docker Hub account with the following command:
Enter the password when prompted to log in.
2. Push the image to the Docker Hub with:
The image is now visible on your Docker Hub page and available for use.
3. To pull the image to a different machine, use:
Alternatively, stop the docker container and remove the container and image from the current machine. Pull the image and use the same docker run
command from step 5 to build the container.
Conclusion
After going through the steps in this guide, you should know how to build a Node.js app with Docker.
Next, read about Docker container best practices.