How to Run This NestJS Blog Project in Docker: Building the Image, Starting the Container, and Opening It
A step-by-step guide for students new to Docker — three commands take you from source code to a running blog at localhost:3000, with an explanation of what each one does.
Goal
Run this blog on your own machine inside a Docker container, without installing Node.js.
Everything the project needs — Node 20, the dependencies, the compiled code — is built into the image. If Docker is installed, you have enough.
Before you start
Docker must be installed and running.
Open a terminal in the automation/ folder. This matters: it holds the Dockerfile and
package.json, and Docker looks for them in the folder you run the command from.
cd AWS_Demo_Project/automation
Step 1 — Build the image
An image is a packaged snapshot of the application: the code, its dependencies, and the Node runtime, frozen together.
docker build -t blog .
-t bloggives the image a name, so you can refer to it asbloglater.means "build using this folder" — it is not a typo, and it must be there
The first build takes a minute or two. It installs the npm packages and compiles the TypeScript
inside the image. Wait until it finishes and you see blog:latest mentioned in the last lines.
Step 2 — Run the container
A container is a running instance of that image. The image is the recipe; the container is the meal.
docker run -d --name blog -p 3000:3000 \
-e ADMIN_PASSWORD=dev-password \
-v blog_data:/app/data \
blog
On Windows PowerShell the \ continuation does not work, so use one line:
docker run -d --name blog -p 3000:3000 -e ADMIN_PASSWORD=dev-password -v blog_data:/app/data blog
What each part does:
| Part | Meaning |
|---|---|
-d |
Run in the background and give your terminal back |
--name blog |
Name the container blog so later commands are easy to type |
-p 3000:3000 |
Connect port 3000 on your machine to port 3000 inside the container |
-e ADMIN_PASSWORD=dev-password |
Sets the admin password. Without it, you cannot sign in at all |
-v blog_data:/app/data |
Saves posts and images outside the container, so they are not lost |
blog |
The image to run — the one you built in Step 1 |
You will see a long string of letters and numbers. That is the container ID, and it means the container started.
Step 3 — Open it
The blog seeds itself with a few starter posts the first time it runs.
To sign in to the admin, go to http://localhost:3000/login and use the password you passed
above — dev-password.
| Page | URL |
|---|---|
| Blog | http://localhost:3000 |
| Admin | http://localhost:3000/admin |
| Login | http://localhost:3000/login |
| Health check | http://localhost:3000/health |
Useful commands
Check that it is running:
docker ps
See the application logs (add -f to keep watching):
docker logs blog
Stop and remove the container:
docker stop blog
docker rm blog
If you change the code
The image was built with a copy of the code inside it, so editing a file on your computer does not change the running container. You have to rebuild:
docker stop blog
docker rm blog
docker build -t blog .
docker run -d --name blog -p 3000:3000 -e ADMIN_PASSWORD=dev-password -v blog_data:/app/data blog
Your posts survive this. They are stored in blog_data, which lives outside the container.
Common problems
| Problem | Fix |
|---|---|
port is already allocated |
Something else is using port 3000. Stop it, or use -p 8080:3000 and open port 8080 instead |
container name "/blog" is already in use |
An old container is still there. Run docker rm blog first |
| Cannot sign in | You forgot -e ADMIN_PASSWORD=dev-password |
| Page does not load | Check docker ps. If the container is not listed, run docker logs blog to see why it stopped |
| Posts disappeared | The -v blog_data:/app/data part was missing when you started the container |