Containerize a Website with Docker

Package a static website into a Docker image and publish it to Docker Hub.

Introduction

30 Second Summary

Imagine if you could package your entire website into a single box that runs exactly the same on any computer in the world. No missing files, no broken dependencies, no "it works on my machine" problems.

In this project, you will take a real website from GitHub, package it into a Docker container image, run it live in your browser, and publish it to Docker Hub so anyone can pull and run it with a single command.

What You'll Build

You will run one command and watch a professional portfolio website with a particle animation background appear in your browser, served entirely from inside a container that you built and published yourself.

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

  • A running container serving a live website in your browser, proving you can package and run any static site with a single command.
  • A shareable one-liner that anyone can use to pull your image from Docker Hub and run your exact website on their own machine.
  • A published image on Docker Hub listed alongside millions of other public images, ready for the world to use.
  • **Secret Mission:** Secret Mission: Optimize your image with a .dockerignore file and publish a versioned tag.

Are there any prerequisites?

You will need Docker Desktop installed on Windows and a free Docker Hub account. This project walks you through verifying both are ready in Step 1, so no prior Docker experience is required.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters. This step is your chance to commit to the goal before any hands-on work begins.

Set Up Your Environment

Before building anything, you need to confirm that Docker Desktop is running on your machine and that you can talk to Docker Hub.

Docker Desktop is the engine that builds and runs containers. Docker Hub is the public registry where you'll publish your finished image. This step verifies both are ready to go.

In this step, get ready to:
  • Verify Docker Desktop is running.
  • Log in to Docker Hub from the terminal.
Verify Docker Desktop is running
  • Press the Windows key to open your search bar.
  • Type PowerShell and press Enter to open it.
  • Check that Docker is running by running this command:
docker --version

✔️ I see a version number

You should see something like Docker version 28.x.x. Docker Desktop is running and ready. Move on to the next substep.

ⓧ I see an error about the Docker daemon

If you see an error mentioning the Docker daemon is not running, Docker Desktop has not started yet.

  • Press the Windows key to open your search bar.
  • Type Docker Desktop and press Enter to launch it.
  • Wait about 30 seconds for Docker Desktop to finish starting. You'll see a green whale icon in the system tray when it's ready.
  • Run the version command again:
docker --version

You should now see a version number printed.

Log in to Docker Hub

Docker Hub requires authentication before you can push images to your account. The docker login command uses a web-based device code flow to authenticate you.

Before you run this, what do you think the login process will look like? Will it ask for your password right in the terminal, or handle it differently?

  • Log in to Docker Hub by running this command:
docker login

What happens when you run this?

Docker displays a one-time device confirmation code and a URL. It does not ask for your password in the terminal.

Press Enter to open the browser. Enter the code shown in your terminal on the page that opens, then confirm the login. Your terminal prints Login Succeeded when authentication is complete.

  • Press Enter when prompted to open the browser.
  • Enter the device confirmation code shown in your terminal into the browser page.
  • Confirm the login in the browser.
  • Switch back to your terminal. You should see Login Succeeded printed.

✔️ I see Login Succeeded

You're authenticated with Docker Hub. Any images you push will land in your account.

ⓧ I see an error or the browser did not open

  • If the browser did not open automatically, copy the URL shown in the terminal and paste it into your browser manually.
  • Make sure you enter the code exactly as shown in the terminal. The code is case-sensitive.
  • If you see a timeout error, run docker login again and complete the browser step within 15 minutes.

Once you see Login Succeeded in the terminal, you're good to go.

Still not seeing Login Succeeded?

Make sure Docker Desktop is still running. If it stopped, restart it and try docker login again.

Help me troubleshoot my Docker login issue

Your environment is ready. Docker is running and you're authenticated with Docker Hub. Next up, you'll clone a real website and write the Dockerfile that packages it into a container image.

Clone the Website and Write a Dockerfile

Your Docker environment is ready and authenticated with Docker Hub. Now you need actual files to containerize.

Docker can't package a website without instructions. A Dockerfile is a short recipe that tells Docker exactly what to include in an image and how to serve it. In this step, you'll clone a real portfolio website and write that recipe.

In this step, get ready to:
  • Clone an open-source portfolio website from GitHub.
  • Write a Dockerfile that packages the site with an Nginx web server.
Clone the portfolio website from GitHub

You'll work with a real open-source portfolio site hosted on GitHub. It's a static HTML/CSS/JS personal website with a particle animation background. No build tools required.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Clone the portfolio website and move into the project folder by running these commands:
git clone https://github.com/brendanjowett/personal-website.git
cd personal-website

You'll see Git download the repository files. Once the clone is complete, you're inside the personal-website folder.

  • Confirm the website files are present by running:
dir

You should see files like index.html, style.css, script.js, and network.js listed in the output.

Seeing 'git' is not recognized?

Make sure Git is installed on your machine. Open the Start menu, search for Git, and check if it appears. If not, download and install it from git-scm.com. After installing, close and reopen your terminal before trying again.

help me fix a 'git is not recognized' error on Windows

Create a Dockerfile

A Dockerfile tells Docker which base image to start from and what files to copy in. Your Dockerfile will use Nginx as the web server and copy your website files into the directory Nginx serves from.

  • Open a new file called Dockerfile in Notepad by running:
notepad Dockerfile

What will Notepad ask me?

Notepad will ask if you want to create a new file since Dockerfile doesn't exist yet. Click Yes to continue. Because you opened the file by name from the terminal, Notepad saves it with the exact name Dockerfile (no .txt extension added).

  • Type the following two lines into the Notepad window:
FROM nginx:1.31.3
COPY . /usr/share/nginx/html

What does this Dockerfile do?

FROM nginx:1.31.3 tells Docker to start from the official Nginx image at version 1.31.3. This gives you a fully working web server out of the box.

COPY . /usr/share/nginx/html copies every file in your current folder into /usr/share/nginx/html. That's the directory Nginx serves files from by default. When the container runs, Nginx automatically serves your website.

  • Save the file by pressing Ctrl+S.
  • Close Notepad to return to your terminal.

Before you check the directory listing, what files do you expect to see alongside index.html and style.css?

  • Verify the Dockerfile was created by running:
dir

You should see Dockerfile listed alongside the website files (index.html, style.css, script.js). Your recipe is ready for Docker to read.

Don't see Dockerfile in the list?

If you see Dockerfile.txt instead of Dockerfile, Notepad added a .txt extension. Rename it by running:

ren Dockerfile.txt Dockerfile

If you don't see it at all, make sure you saved the file in Notepad (Ctrl+S) before closing. Also confirm your terminal is still inside the personal-website folder by checking the path shown in your prompt.

help me fix my Dockerfile not appearing in the project folder

✔️ Awesome, I've got everything!

Great. Make sure you've saved your Dockerfile and that Notepad is closed before moving on.

ⓧ I'd like to double check the full code

Your Dockerfile should contain exactly these two lines:

FROM nginx:1.31.3
COPY . /usr/share/nginx/html

Your website files and Dockerfile are in place. Next up, you'll build this recipe into a real Docker image and run it as a live container in your browser.

Build and Run Your Container

Your Dockerfile is ready. It tells Docker exactly what to put inside your image and how to serve your site.

Now it's time to put that recipe to work. Building creates a container image (a frozen snapshot of your website plus the web server), and running it starts a live container you can visit in your browser.

In this step, get ready to:
  • Build a Docker image from your Dockerfile.
  • Run a container and see your website live in the browser.
  • Confirm the container is running with docker ps.
Build the Docker image

Building an image reads your Dockerfile and packages everything into a reusable snapshot. Once built, you can run as many containers from it as you like.

  • Build your Docker image by running this command:
docker build -t my-website .

What does this command do?

  • docker build tells Docker to read your Dockerfile and create an image from it.
  • -t my-website names (tags) your image "my-website" so you can reference it later.
  • . tells Docker to use the current directory as the build context. Docker sends all the files in this folder to the build engine.

Watch the terminal output as Docker pulls the Nginx base image and copies your website files into it. When it finishes, you'll see a line that says Successfully tagged my-website:latest.

Seeing an error during the build?

  • Make sure Docker Desktop is running. You can check by looking for the Docker whale icon in your system tray.
  • Confirm your terminal is inside the personal-website folder where your Dockerfile lives. Run dir and check that Dockerfile appears in the listing.
  • If you see a network error while pulling the nginx image, check your internet connection and try again.

Why is my Docker build failing?

Run a container from your image

Your image is built. Now you can start a container from it. The container runs the Nginx web server and serves your website on a port you choose.

  • Start a container from your image by running:
docker run -d -p 8080:80 my-website

What do these flags mean?

  • -d runs the container in the background (detached mode) so your terminal stays free.
  • -p 8080:80 maps port 8080 on your machine to port 80 inside the container. Nginx listens on port 80 by default, so this lets you reach it at localhost:8080.
  • my-website is the name of the image you built in the previous command.

Docker will print a long string of characters (the container ID) and return you to the terminal prompt. Your container is now running in the background.

What do you expect to see when you open http://localhost:8080 in your browser?

  • Open http://localhost:8080 in your browser.

You should see the personal website with its particle animation background. That entire site is being served from inside your Docker container by Nginx.

Don't see the website?

  • Make sure you typed http://localhost:8080 exactly. Port 8080 is what you mapped, not port 80.
  • If the page says "connection refused", the container may have stopped. Run docker ps to check if it's listed. If it's not, run docker ps -a to see stopped containers and check the STATUS column for errors.
  • If another service is already using port 8080, you'll get a "port already in use" error. Stop the other service or change the port to 9090 by re-running with -p 9090:80 instead.

Why can't I see my website at localhost:8080?

Confirm the container is running
  • Check your running containers by running:
docker ps

You should see your container listed with the image name my-website and the port mapping 0.0.0.0:8080->80/tcp. This confirms Nginx is listening inside the container and your port mapping is active.

Container not showing in docker ps?

  • If docker ps shows nothing, the container crashed immediately after starting. Run docker ps -a to find it, then run docker logs <container-id> to see the error output.
  • A common cause is a syntax error in the Dockerfile. Double-check that your Dockerfile matches the two lines exactly: FROM nginx:1.31.3 and COPY . /usr/share/nginx/html.

Help me figure out why my container stopped immediately.

Your website is live inside a container on your machine. Next up, you'll push this image to Docker Hub so anyone in the world can pull and run it.

Push Your Image to Docker Hub

Your website is running in a container on your machine. Anyone at your laptop can visit http://localhost:8080 and see it live. But what about everyone else?

In this step, you will push your Docker image to Docker Hub, a public registry where anyone in the world can download and run it. Along the way, you will discover why Docker Hub cares about how you name your images.

In this step, get ready to:
  • Attempt to push your local image to Docker Hub.
  • Fix the image name using Docker's tagging system.
  • Push the correctly tagged image and verify it on Docker Hub.
Attempt to push your image

Your image is built and your container is running. The next logical step is to share it with the world by pushing it to Docker Hub.

Before you run this command, take a guess. Do you think pushing an image named my-website will succeed? Why or why not?

  • Try pushing your image to Docker Hub by running this command:
docker push my-website

You will see an error message that includes requested access to the resource is denied.

Why did this fail?

Docker Hub does not know which account to push to. The image name my-website has no username prefix, so Docker Hub cannot match it to any repository.

Docker Hub requires images to follow the format username/repository. This tells Docker Hub exactly where the image belongs.

Tag the image with your Docker Hub username

Tagging creates a new reference to the same image with the correct naming format. Think of it as giving your image a second name that Docker Hub can understand.

  • Tag your image with your Docker Hub username by running this command:
docker tag my-website [[DOCKER_USERNAME="your-docker-username"]]/my-website

What does this command do?

docker tag does not create a copy of the image. It adds a second name (a "tag") pointing to the exact same image data.

The format username/repository tells Docker Hub which account owns the image and what to call the repository.

  • Confirm both names exist by running:
docker images

You should see both my-website and your-docker-username/my-website listed with the same image ID.

Only see one entry?

Make sure you replaced the username placeholder with your actual Docker Hub username. The tag command does not produce any output on success, so if you got no error, it worked. Run docker images again and look for two rows with matching image IDs.

help me fix my docker tag command

Push the correctly tagged image

Now that your image has the correct username prefix, Docker Hub will know exactly where to put it.

What do you think will happen this time when you push? Will Docker Hub accept the image now that it has your username in the name?

  • Push your tagged image to Docker Hub by running this command:
docker push [[DOCKER_USERNAME="your-docker-username"]]/my-website

Watch as Docker uploads each layer to Docker Hub. Once complete, you will see a digest and size summary for each layer pushed.

What does this output mean?

Docker images are made of layers. Each line in the output represents one layer being uploaded. The latest tag is applied automatically when you do not specify a version.

Docker Hub auto-creates the repository if it does not already exist. You do not need to set anything up on the website first.

  • Open your browser and visit https://hub.docker.com.
  • Sign in and click on Repositories in the top navigation.
  • You should see your my-website repository listed with the latest tag.

Don't see your repository on Docker Hub?

Make sure the push command finished without errors. Check that you are signed in to Docker Hub with the same account you used for docker login in Step 1.

If you see a "denied" error, run docker login again to re-authenticate, then retry the push.

help me push my Docker image to Docker Hub

Secret mission

Optimize Your Image with .dockerignore

Your published image works, but it contains files that have no business being in production. The .git folder, README.md, and config files bloat the image and leak repository metadata. In this mission, you will create a .dockerignore file to slim down your build context and publish a versioned tag to Docker Hub.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally with a free Docker Hub public repository, so there are no ongoing costs.

Resources you used:

  • Running Docker container serving the website at http://localhost:8080.
  • Local Docker images (my-website, YOUR-DOCKER-USERNAME/my-website, YOUR-DOCKER-USERNAME/my-website:v2).
  • Docker Hub repository (YOUR-DOCKER-USERNAME/my-website with latest and v2 tags).
  • Local project folder (personal-website on your Desktop).

Keep everything running

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

  • Your container continues serving the website at http://localhost:8080.
  • Your Docker images remain available locally for instant container launches.
  • Your Docker Hub repository stays public for anyone to pull.

Pause - I'll come back to this later

Stop the running container to free up memory and port 8080. Your images and files stay on disk so you can restart anytime.

  • Find your running container's ID by running:
docker ps
  • Copy the container ID from the first column, then stop it by running:
docker stop [[CONTAINER_ID="your container ID from docker ps"]]

To restart later, run the same docker run command from Step 3 and your site will be back at http://localhost:8080.

Delete - I don't want to use this again

Remove all project resources from your machine and Docker Hub. This is permanent.

  • Stop and remove the running container by running:
docker ps -q --filter ancestor=my-website | ForEach-Object { docker stop $_; docker rm $_ }
  • Remove the local Docker images by running:
docker rmi my-website
docker rmi [[DOCKER_USERNAME="YOUR-DOCKER-USERNAME"]]/my-website
docker rmi [[DOCKER_USERNAME="YOUR-DOCKER-USERNAME"]]/my-website:v2
  • Delete the local project folder by running:
cd ~\Desktop
Remove-Item -Recurse -Force personal-website
  • Delete the Docker Hub repository:
  • Sign in to Docker Hub.
  • Select My Hub then Repositories.
  • Select your my-website repository.
  • Select the Settings tab.
  • Select Delete repository.
  • Enter the repository name to confirm, then select Delete Repository Forever.

Nice Work!

Nice Work!

You just containerized a real website with Docker and published it to the world. Anyone with Docker installed can now run your site with a single docker pull and docker run command.

Here's what you accomplished:

  • Wrote a Dockerfile to package a static website into a container image using Nginx as the web server.
  • Built a Docker image and ran a live container serving the website in your browser at localhost:8080.
  • Tagged and pushed your image to Docker Hub, learning the registry naming convention by hitting a real push error and fixing it with docker tag.
  • Secret Mission: Optimized your image with a .dockerignore file and published a versioned v2 tag to Docker Hub.

Ready to quiz yourself?