Containerize a Node.js App with Docker

Package a Node.js todo app into a Docker container and run it locally.

Introduction

30 Second Summary

You just finished building an app on your computer and it works perfectly. But when a teammate tries to run it on their machine, nothing works. Different versions, missing files, broken settings. This is one of the most common problems in software development.

In this project, you will package a Node.js web application inside a Docker container. This makes the app portable and reproducible, so it runs exactly the same way on any machine.

What You'll Build

You will containerize a todo list app using Docker, then build, run, stop, and redeploy it from the command line.

By the end of this project, you'll have:

  • A custom Dockerfile that defines how to package your app into a portable image.
  • A running container serving a todo list app you can open in your browser.
  • Hands-on experience with core Docker commands for building images, running containers, and managing their lifecycle.
  • Secret Mission: Make a code change, rebuild the image, and redeploy to see your update live.

Are there any prerequisites?

None. This project includes full setup instructions for Docker Desktop, Git, and VS Code. You do not need to know Node.js to complete this project.

Install Docker Desktop and Git

Before you can run containers, you need a container engine on your machine. Docker Desktop provides the Docker engine along with a graphical interface for managing containers on Windows.

In this step, you will install Docker Desktop, verify it works, and set up Git and VS Code so you have everything ready to containerize the sample app.

In this step, get ready to:
  • Install Docker Desktop with the WSL 2 backend.
  • Verify Docker can pull and run containers.
  • Install Git and VS Code.
Download and install Docker Desktop

Docker Desktop is the application that runs the Docker engine on Windows. It uses WSL 2 (Windows Subsystem for Linux) as its backend to run Linux containers efficiently.

  • Open your browser and go to the Docker Desktop download page:
  • https://docs.docker.com/desktop/install/windows-install/
  • Click the download button to get Docker Desktop Installer.exe.
  • Double-click Docker Desktop Installer.exe to run the installer.
  • When the installer asks which mode you prefer, choose Per-user installation (recommended). This does not require admin privileges.
  • If you see a Configuration page with a Use WSL 2 instead of Hyper-V option, make sure it is selected.
  • Wait for the installation to finish. The installer may ask you to restart your computer to enable WSL 2 features. If prompted, restart and come back to this step.
  • Press the Windows key to open your search bar.
  • Type Docker Desktop and press Enter to launch it.
  • Accept the Docker Subscription Service Agreement when prompted.

What is Docker Desktop?

Docker Desktop is a free application for personal use, education, and small businesses. It installs the Docker engine, a CLI, and a dashboard for managing your containers all in one package.

The per-user installation uses the WSL 2 backend exclusively. WSL 2 gives Docker access to a real Linux kernel on Windows, which is how it runs Linux containers natively.

Docker Desktop may take a moment to start

The first time Docker Desktop launches, it needs to set up its internal WSL 2 distribution. Wait until the Docker Desktop dashboard fully loads and the bottom-left status shows a green indicator before moving on.

Verify Docker is working

Now that Docker Desktop is running, you will verify the installation from PowerShell. PowerShell is the terminal you will use for all Docker commands in this project.

  • Press the Windows key to open your search bar.
  • Type PowerShell and press Enter to open it.
  • Check your Docker version by running this command:
docker --version

✔️ I see a version number

Docker is installed and ready. You should see output like Docker version 28.x.x or similar. The exact version number does not matter as long as a version appears.

ⓧ Command not found or error

If PowerShell does not recognize the docker command, try these fixes:

  • Make sure Docker Desktop is running. Check for the Docker whale icon in your system tray (bottom-right of your taskbar).
  • Close PowerShell and reopen it. Docker adds itself to your system PATH during installation, but PowerShell only picks up PATH changes when it starts a new session.
  • If you restarted your computer during installation, launch Docker Desktop again before retrying.

help me troubleshoot why docker --version is not working in PowerShell

Next, confirm Docker can actually pull and run a container. This is the real test.

  • Run the hello-world test container by running this command:
docker run hello-world

✔️ I see a Hello from Docker message

Docker pulled the hello-world image from Docker Hub and ran it in a container. The confirmation message means your Docker installation is fully working. You are ready to move on.

ⓧ I see an error

If you see an error about the Docker daemon not running or a connection issue, try these fixes:

  • Confirm Docker Desktop is fully started. Wait for the dashboard to load and the green status indicator to appear in the bottom-left corner.
  • If you see a message about WSL 2 not being installed, open PowerShell as Administrator and run wsl --install. Restart your computer, then launch Docker Desktop again.
  • Try running the command again after waiting 30 seconds for Docker to fully initialize.

help me fix docker run hello-world failing on Windows

Install Git and VS Code

You need Git to download the sample app repository. You also need VS Code to edit files in later steps.

  • Check if Git is already installed by running this command in PowerShell:
git --version

✔️ I see a version number

Git is already installed. You are good to go.

ⓧ Command not found

  • Open your browser and go to the Git download page:
  • https://git-scm.com/downloads/win
  • Download and run the installer. Accept the default settings throughout the wizard.
  • Close and reopen PowerShell after installation.
  • Run git --version again to confirm it works.

Finally, confirm you have VS Code installed.

  • Press the Windows key, type Visual Studio Code, and check if it appears in search results.
  • If VS Code is not installed, download it from https://code.visualstudio.com/ and run the installer.

Having trouble with any of these installs?

Installation issues are almost always caused by needing to restart PowerShell (or your whole computer) after an installer modifies your system PATH. Close PowerShell, reopen it, and try the version check command again.

help me troubleshoot installing Docker Desktop, Git, or VS Code on Windows

Your environment is ready. Next up, you will clone the sample Node.js app that you are going to containerize.

Clone the Sample App

In the previous step, you installed Docker Desktop, Git, and VS Code. Your development environment is ready to go.

Now you need an application to containerize. Instead of writing one from scratch, you'll clone a pre-built Node.js todo app from Docker's official sample repository.

In this step, get ready to:
  • Clone the Docker sample app repository.
  • Explore the project file structure in VS Code.
Clone the getting-started app

Docker provides an official sample repository with a simple todo list app. You'll clone this repository to your Desktop so you can easily find it later.

  • Move to your Desktop by running this command in PowerShell:
cd ~/Desktop
  • Download the sample app and move into the project folder by running these commands:
git clone https://github.com/docker/getting-started-app.git
cd getting-started-app

What do these commands do?

  • git clone downloads the entire repository from GitHub to your machine, creating a folder called getting-started-app.
  • cd getting-started-app moves your terminal session into that new folder so all future commands run from inside the project.
  • Confirm the project files exist by running:
ls

You should see entries including package.json, src, and spec in the output.

Seeing an error about the repository?

  • Make sure you have an active internet connection. The git clone command downloads files from GitHub.
  • If you see a message about git not being recognized, close and reopen PowerShell. The PATH update from installing Git may not have taken effect yet.
  • If ls shows no files, make sure you ran cd getting-started-app after the clone command.

help me troubleshoot my git clone command in PowerShell

Open the project in VS Code

Now that the files are on your machine, you'll open them in VS Code to see what the app contains.

  • Open the project in VS Code by running this command:
code .

VS Code opens with the getting-started-app folder loaded. In the Explorer sidebar on the left, you should see:

  • package.json at the top level.
  • A src/ folder containing the app source code.
  • A spec/ folder containing tests.

Why is there no Dockerfile?

This sample app is just a regular Node.js application. It has no Docker configuration yet. In the next step, you will create a Dockerfile that tells Docker how to package this app into a container image.

VS Code did not open?

  • If PowerShell does not recognize the code command, VS Code may not be in your system PATH. Reinstall VS Code and check the option to add it to PATH during setup. Then close and reopen PowerShell.
  • Alternatively, open VS Code manually. Press the Windows key, type VS Code, and press Enter. Then click File in the menu bar, select Open Folder, and navigate to Desktop > getting-started-app.

help me get the code command working in PowerShell on Windows

Your project files are ready. Next up, you'll write a Dockerfile that tells Docker exactly how to package this app into a container image.

Write a Dockerfile

Your project is open in VS Code with all the app's source code ready to go. The missing piece is a set of instructions that tells Docker how to package this code into a runnable container image.

In this step, you'll create a Dockerfile. This is the recipe that Docker follows to build an image of your app, layer by layer.

In this step, get ready to:
  • Create a Dockerfile in the project root.
  • Understand what each instruction in the Dockerfile does.
Create the Dockerfile

A Dockerfile is a plain text file with no extension. Each line is an instruction that tells Docker what to put inside the image and how to configure it.

  • In VS Code, hover over the project name at the top of the Explorer sidebar to reveal the action icons.
  • Click the New File... icon (a page with a plus sign).
  • Type Dockerfile and press Enter.
  • Paste the following code into the new file:
# syntax=docker/dockerfile:1

FROM node:24-alpine
WORKDIR /app
COPY . .
RUN npm install --omit=dev
CMD ["node", "src/index.js"]
EXPOSE 3000

What does each line do?

  • # syntax=docker/dockerfile:1 enables the latest Dockerfile parsing features from Docker BuildKit.
  • FROM node:24-alpine picks a lightweight Linux image with Node.js pre-installed. Alpine is a tiny Linux distribution, so your image stays small.
  • WORKDIR /app sets the working directory inside the container. All following commands run from this folder.
  • COPY . . copies your source code from your machine into the container's /app directory.
  • RUN npm install --omit=dev installs the app's dependencies inside the container, skipping development-only packages.
  • CMD ["node", "src/index.js"] tells Docker how to start your app when the container launches.
  • EXPOSE 3000 documents which port the app listens on. This helps anyone reading the Dockerfile understand how to connect to the app.
  • Save the file with Ctrl+S.
  • Confirm the file appears in the Explorer sidebar as Dockerfile (no extension) at the same level as package.json.

Don't see the Dockerfile in the Explorer?

  • Make sure you named it exactly Dockerfile with a capital D and no file extension like .txt. If VS Code added an extension automatically, rename the file.
  • Check that the file is at the root level of getting-started-app, not inside the src/ or spec/ folder. If it ended up in a subfolder, drag it to the top level in the Explorer.
  • If you see a file called Dockerfile.txt, right-click it in the Explorer and select Rename to remove the extension.

Why isn't my Dockerfile showing up correctly?

✔️ Awesome, I've got everything!

Great. Double check you've saved the file before moving on.

ⓧ I'd like to double check the full code

Here is the complete Dockerfile:

# syntax=docker/dockerfile:1

FROM node:24-alpine
WORKDIR /app
COPY . .
RUN npm install --omit=dev
CMD ["node", "src/index.js"]
EXPOSE 3000

Your Dockerfile is locked in. Next up, you'll feed it to Docker to build an image and spin up your first running container.

Build and Run Your Container

Your Dockerfile is written and ready to go. It defines exactly how Docker should package your app into a portable image.

Now it's time to put that Dockerfile to work. In this step, you'll build a Docker image and launch it as a running container that serves your todo app in the browser.

In this step, get ready to:
  • Build a Docker image from your Dockerfile.
  • Run the image as a container with port mapping.
  • Verify the todo app is accessible at localhost:3000.
Build your Docker image

The docker build command reads your Dockerfile and creates an image. Each instruction in the Dockerfile becomes a layer in the final image.

  • Build your Docker image by running this command in PowerShell:
docker build -t getting-started .

What does this command do?

  • -t getting-started tags the image with the name getting-started so you can reference it later by name instead of a random ID.
  • . tells Docker to look in the current directory for the Dockerfile and use this folder as the build context.

Docker downloads the base image layers, copies your code, and installs dependencies. This may take a minute on the first run.

  • You should see Docker processing each step in your Dockerfile. When it finishes, your terminal returns to the prompt with no error messages.

Seeing an error during the build?

  • Make sure Docker Desktop is running. Check your taskbar for the Docker whale icon.
  • Confirm you are inside the getting-started-app directory where your Dockerfile lives. Run ls and check that Dockerfile appears in the output.
  • Check that your Dockerfile has no file extension. Windows sometimes adds .txt automatically. Rename it if needed.

Why is my Docker build failing?

Run the container

Your image is built. Now you can run it as a container. A container is a live, running instance of your image.

  • Start your container by running this command:
docker run -d -p 127.0.0.1:3000:3000 getting-started

What do these flags mean?

  • -d runs the container in detached mode. This means it runs in the background and gives you your terminal back.
  • -p 127.0.0.1:3000:3000 maps port 3000 on your machine to port 3000 inside the container. This is how you access the app from your browser.
  • getting-started is the name of the image you just built.

Docker prints a long container ID string. This confirms your container is running in the background.

  • Open http://localhost:3000 in your browser. You should see the todo list app.
  • Add a few items, mark them as complete, and remove them to confirm the app is fully functional.

Page not loading at localhost:3000?

  • Make sure you don't already have something running on port 3000. Close any other dev servers or apps that might be using that port.
  • Run docker ps to check if your container is actually running. If nothing appears, the container may have crashed on startup.
  • Check that you typed 127.0.0.1:3000:3000 in the -p flag, not a different port number.

Why can't I access my Docker container at localhost:3000?

Your containerized app is live and serving traffic from inside a Docker container. Next up, you'll learn how to stop, remove, and restart containers to manage your app's lifecycle.

Manage Your Container

Your todo app is live inside a Docker container. Now it's time to learn how to control that container: stopping it, removing it, and spinning up a fresh one.

In real workflows, you'll constantly start and stop containers as you develop, test, and deploy. Docker gives you a handful of commands to manage this entire lifecycle from your terminal.

In this step, get ready to:
  • Inspect running containers with docker ps.
  • Stop and remove a container.
  • Restart a fresh container from your existing image.
View your running containers

Docker keeps track of every container running on your machine. You can ask Docker to show you a list at any time.

  • See your running containers by running this command in PowerShell:
docker ps

You should see one entry showing your getting-started image, along with a container ID, status, and port mapping.

  • Find the CONTAINER ID column in the output. Copy your container ID (a short alphanumeric string). You'll need it for the next commands.

What does docker ps show?

The docker ps command lists all currently running containers. Each row shows the container ID, the image it was created from, when it was started, its current status, and port mappings.

The container ID is how you refer to a specific container when you want to stop or remove it.

Stop and remove the container

Before you can redeploy or make changes, you need to stop the running container and remove it. Docker requires you to stop a container before removing it.

  • Stop the running container by running this command (replace the container ID with yours):
docker stop [[CONTAINER_ID="your container ID from docker ps"]]

Docker prints the container ID back to confirm it stopped the container.

  • Remove the stopped container by running this command:
docker rm [[CONTAINER_ID="your container ID from docker ps"]]

Docker prints the container ID again to confirm removal.

  • Verify the container is gone by running:
docker ps -a

This shows all containers, including stopped ones. Your getting-started container should no longer appear in the list.

What is the difference between stop and rm?

Stopping a container shuts down the running process but keeps the container's filesystem on disk. Removing a container deletes it entirely.

Think of it like quitting an app versus uninstalling it. You need to stop first, then remove.

Seeing an error when stopping or removing?

  • Make sure you copied the correct container ID from the docker ps output. Even the first few characters of the ID are enough.
  • If docker rm says the container is still running, run docker stop first. You must stop a container before removing it.

Help me troubleshoot a Docker stop or remove error

Start a fresh container

Your Docker image still exists even though the container is gone. You can spin up a new container from that image anytime you want.

  • Start a fresh container by running this command:
docker run -d -p 127.0.0.1:3000:3000 getting-started
  • Open http://localhost:3000 in your browser.

You should see the todo list app running again. This proves you can destroy and recreate your container at any time from the image you built.

Why is the todo list empty?

Any items you added earlier are gone because you removed the old container. Containers are ephemeral by default. When you remove one and start a new one, you get a fresh filesystem.

Persisting data across container restarts requires Docker volumes, which is a topic for a future project.

Port already in use?

  • If you see a port conflict error, the previous container may not have been fully removed. Run docker ps to check for any running containers using port 3000.
  • Stop and remove any leftover container, then try the docker run command again.

Help me fix a Docker port conflict

Secret mission

Update the App and Redeploy

You've built and run your container. But what happens when you need to change something? In this mission, you'll make a code change, rebuild the image, and redeploy to see your update live.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine using Docker Desktop, which is free for personal use and education. There are no ongoing cloud costs.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Docker container(s) running the getting-started image.
  • Docker image tagged getting-started.
  • Docker image hello-world (pulled during verification).
  • The getting-started-app folder on your Desktop.
  • Docker Desktop (installed application).

Keep everything running

No action needed. Choose this if you are still actively building or plan to experiment more with Docker commands.

  • Your container continues running in the background and remains accessible at http://localhost:3000.
  • Docker Desktop stays installed and ready for future projects.
  • The getting-started-app folder stays on your Desktop for reference.

Pause - I'll come back to this later

Stop running containers to free up memory and CPU, but keep your image and files so you can restart quickly.

  • Open PowerShell and find your running container by running:
  • Stop the container by running:
docker ps

Copy the container ID from the output, then stop it:

docker stop <container-id>

Your image and files remain intact. To restart later, run:

docker run -d -p 127.0.0.1:3000:3000 getting-started

Delete - I don't want to use this again

Remove all project resources and optionally uninstall Docker Desktop to start completely fresh.

  • Stop and remove all containers created from the getting-started image. First, find them:
docker ps -a
  • For each container ID listed that uses the getting-started or hello-world image, stop and remove it:
docker stop <container-id>
docker rm <container-id>
  • Remove the Docker images:
docker rmi getting-started
docker rmi hello-world
  • Delete the project folder. In PowerShell, navigate to your Desktop and run:
cd ~/Desktop
Remove-Item -Recurse -Force getting-started-app
  • To uninstall Docker Desktop, open Settings from the Windows Start menu.
  • Select Apps, then Apps & features.
  • Find Docker Desktop in the list and click Uninstall.
  • Confirm the uninstallation when prompted.

That's a Wrap!

That's a Wrap!

Nice work! You just containerized a Node.js application with Docker and proved you can package, run, and manage apps in portable containers.

You've learned how to:

  • Built a custom Docker image from a Dockerfile that packages a Node.js app with all its dependencies.
  • Ran a container with port mapping and accessed a live web app at localhost:3000.
  • Managed the full container lifecycle using docker ps, docker stop, and docker rm.
  • Secret Mission: Updated the app source code, rebuilt the image, and redeployed to see your changes live.

Ready to quiz yourself?