How to Serve a Static App with nginx in Docker

Nick Scialli
March 07, 2021

New — Check out my free newsletter on how the web works!

docker and nginx logos

Let’s create a static site and learn how to serve it in a Docker container using nginx. First, we’ll want to create a simple static site with some assets.

Creating a Sample Site

We can make a directory called static-site-nginx and, within that directory, let’s make an index.html file, a styles.css file, and an index.js file.

mkdir static-site-nginx
cd static-site-nginx
touch index.html styles.css index.js

Next up, put the following content in each file. This ends up being a pretty bare-bones site with a styled h1 element and a dynamic counter.


<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Static Site</title>
    <link rel="stylesheet" href="./styles.css" />
    <h1>My counter app</h1>
    <p>Here's the count: <span>0</span></p>
    <button>Click me</button>
    <script src="./index.js"></script>


h1 {
  font-family: sans-serif;
  color: blue;


const count = document.querySelector('span');
const button = document.querySelector('button');
button.addEventListener('click', function () {
  count.textContent = parseInt(count.textContent) + 1;

Running the App (Without Docker First)

Just so we know what we’re dealing with, let’s run the app. I’m using the npm serve package as a local dev server, but any server will work fine.

If we pull the app up in a browser, we should see the following UI / functionality.

counter app

If you’ve gotten this far, great! It’s now time to dockerize the app.

One Required File

Right now, we only need one file to configure our simple static site for Docker: a Dockerfile.

touch Dockerfile

In a more complex app, we might need other files (e.g., a .dockerignore file), but the one file should serve us just fine for now.

Building Out the Dockerfile

Time to build out the Dockerfile! Our Dockerfile config will be relatively trivial: it will just need to have nginx installed, copy over the static assets, and specify the entrypoint for our container.


  • Use an nginx image
  • Remove any default static assets from the nginx image
  • Copy our static assets over
  • Specify the entrypoint for our container to run nginx

Here’s what this looks like in the Dockerfile:

# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets over
COPY ./* ./
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]

Now that we have assembled our Dockerfile, let’s build an image called static-nginx:

docker build -t static-nginx .

Now that our image is built, we can start a container with the following command, which will serve our app on port 8080.

docker run --rm -it -p 8080:80 static-nginx

Navigate to http://localhost:8080, and you should now see our app running!

🎓 Learn how the web works

One of the best ways to level up your tech career is to have a great foundational understanding of how the web works. In my free newsletter, How the Web Works, I provide simple, bite-sized explanations for various web topics that can help you boost your knowledge. Join 2,500+ other learners on the newsletter today!

Signing up is free, I never spam, and you can unsubscribe any time. You won't regret it!

Sign up for the newsletter »
Nick Scialli

Nick Scialli is a senior UI engineer at Microsoft.

© 2024 Nick Scialli