This project demonstrates how to containerize a simple Node.js application using Docker. A Dockerfile was created to package the application into a Docker image, which was then used to create and run a Docker container.
Beyond completing the basic lab, I explored how the CMD instruction controls container startup by testing different startup commands, observing both successful and failed container executions, and restoring the recommended configuration.
- Create a Dockerfile for a Node.js application.
- Build a Docker image from a Dockerfile.
- Run the application inside a Docker container.
- Access the application through a web browser.
- Understand the purpose of common Dockerfile instructions.
- Explore how the
CMDinstruction affects container startup. - Investigate container startup failures using Docker logs.
- Docker
- Dockerfile
- Node.js 20
- Alpine Linux
- Express.js
- Git
- Visual Studio Code
Before running this project, ensure the following are installed:
- Docker Desktop
- Node.js
- Git
- Visual Studio Code (optional)
Write Dockerfile
│
▼
Build Docker Image
│
▼
Run Docker Container
│
▼
Access Application in Browser
│
▼
Experiment with CMD
│
▼
Analyze Results
Dockerfiles-lab/
├── node_modules/
├── screenshots/
├── .gitignore
├── Dockerfile
├── package-lock.json
├── package.json
├── README.md
└── server.js
| File / Folder | Purpose |
|---|---|
Dockerfile |
Contains the instructions Docker follows to build the image. |
package.json |
Defines the application metadata, dependencies, and npm scripts. |
package-lock.json |
Locks dependency versions for consistent builds. |
server.js |
Starts the Express web server and serves the application. |
README.md |
Project documentation. |
.gitignore |
Prevents unnecessary files such as node_modules from being tracked by Git. |
node_modules/ |
Contains the installed project dependencies generated by npm install. |
screenshots/ |
Stores screenshots captured throughout the lab. |
The Dockerfile used in this project is shown below.
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]| Instruction | Description |
|---|---|
FROM node:20-alpine |
Uses the lightweight Node.js 20 Alpine image as the base image. |
WORKDIR /app |
Sets /app as the working directory inside the container. |
COPY package.json package-lock.json ./ |
Copies the dependency files into the container before installing packages. |
RUN npm install |
Installs all project dependencies while building the image. |
COPY . . |
Copies the remaining application files into the image. |
EXPOSE 3000 |
Documents that the application listens on port 3000. |
CMD ["npm","start"] |
Defines the default command Docker executes when a container starts. |
mkdir Dockerfiles-lab && cd Dockerfiles-labgit initnpm installdocker build -t docker-node-app:final .docker imagesdocker run -d -p 3000:3000 --name docker-node-container docker-node-app:finaldocker psdocker stop docker-node-container
docker rm docker-node-containerRunning npm install generated the node_modules directory and the package-lock.json file.
The Docker image was built successfully from the Dockerfile.
The image was then verified.
The application was started by creating a container from the Docker image.
The running container was verified.
The application was successfully accessed through the browser.
To better understand how the CMD instruction works, I experimented with different startup commands.
The original command
CMD ["npm", "start"]was changed to
CMD ["node", "server.js"]The existing container was stopped and removed before rebuilding.
The new image was successfully built.
The application started successfully and displayed the updated browser message.
Both startup commands successfully launched the application because they ultimately execute server.js.
To observe Docker's behavior when an invalid startup command is provided, the Dockerfile was modified to:
CMD ["node", "app.js"]Since app.js does not exist, the container failed to start.
The failure was investigated using Docker logs.
This demonstrated that:
- The Docker image built successfully.
- The container failed only when Docker attempted to execute the incorrect startup command.
- Docker logs provide useful information for troubleshooting container startup failures.
After completing the experiments, the Dockerfile was restored to the original startup command.
CMD ["npm", "start"]The image was rebuilt successfully.
The container was started again.
The application was successfully accessed from the browser.
The node_modules directory contains the installed dependencies required by the application.
"Hello from Docker!" was changed to "Hello from Docker - CMD Experiment!" at the start of Experiment 1.
- Learned how to write a Dockerfile from scratch.
- Built Docker images using
docker build. - Created and managed Docker containers.
- Understood the purpose of
FROM,WORKDIR,COPY,RUN,EXPOSE, andCMD. - Explored different startup commands using the
CMDinstruction. - Investigated container startup failures using Docker logs.
- Reinforced the relationship between a Dockerfile, a Docker image, and a running Docker container.
Through this project, I gained hands-on experience with:
- Writing Dockerfiles
- Building Docker images
- Running and managing Docker containers
- Container lifecycle management (
docker run,docker stop,docker rm) - Docker networking and port mapping
- Understanding Dockerfile instructions (
FROM,WORKDIR,COPY,RUN,EXPOSE,CMD) - Troubleshooting container startup failures using
docker logs - Node.js application containerization
- Git and GitHub project documentation
This lab provided practical experience in containerizing a Node.js application using Docker. Beyond completing the required tasks, I experimented with multiple startup commands to understand how Docker initializes containers and how incorrect configurations affect application startup.
The project reinforced the complete Docker workflow—from writing a Dockerfile to building an image, running containers, troubleshooting failures, and validating successful application deployment through a web browser.


















