How to Serve Static Files with Nginx and Docker

How to Serve Static Files with Nginx and Docker

Let's learn how to serve a static website and static files using an Nginx instance running inside a Docker container. In the end we should be able to serve a static website from a Docker container, like so:

Our static files being served on port 8080.

What is Docker?

Docker is a popular open-source technology for running applications in a containerized environment. This is useful because it allows you to easily scaffold and deploy applications to any platform that supports Docker.

What is Nginx?

Nginx is a popular open-source web server and reverse proxy. It is used to serve static files and to proxy requests to other servers. Nginx is a good choice for serving static files because it is easy to deploy and it is easy to scale. We will use Nginx to serve our static files.

Installing Docker

You will also need to install Docker.

  1. Visit the official Docker website to get the installer.
  2. After it downloads, run the installer until the end.
  3. Restart your computer to ensure the changes can take effect.

The Docker installer.

Directory Structure

By the end of this tutorial, our application will be in the following directory structure:

app
├── static
|   └── index.html
├── docker-compose.yml
└── Dockerfile

Everything we want to serve will be in the static directory. For the purposes of this tutorial, we will use the index.html file as our homepage.

Homepage

Inside the static directory, we will create an index.html file. Add the following to the file:

<!DOCTYPE html>
<html>
    <body>
        <h1>Hello from Sabe!</h1>
    </body>
</html>

This will ensure that the homepage is being served correctly. Now that we have our homepage, we can move on to setting up Docker.

Nginx Configuration

Before we can run Nginx, we need to configure it. We will use the nginx.conf file to do this. Create a file named nginx.conf in the root directory of your folder. Add the following:

events {
    worker_connections 1024;
}

http {
    include mime.types;
    sendfile on;

    server {
        listen 8080;
        listen [::]:8080;

        resolver 127.0.0.11;
        autoindex off;

        server_name _;
        server_tokens off;

        root /app/static;
        gzip_static on;
    }
}

This is a basic Nginx configuration that listens on port 8080 and serves the static files from the /app/static directory. We are also enabling gzip compression for static files.

Docker Overview

Before we continue, let's run through a quick overview of how Docker works. As said before, Docker is a containerization technology that makes it easy to create, deploy, and run applications inside containers.

A Docker container is a lightweight, portable, and isolated unit of software. It is a single process that runs on a single computer. It is designed to run a specific application, such as a web server, or a database.

A Docker image is a blueprint for a Docker container. It is a collection of files and commands that can be used to create a Docker container, and it is stored inside of a file called Dockerfile. The instructions in this file are used to create an image.

Docker overview

Docker Compose

Now that we have an app to deploy and the basic terms for Docker defined, let's deploy it on a Docker container. There are several ways to do this, but the easiest way is to use the Docker Compose tool. It comes with Docker, so you should already have access to it.

Create a file named docker-compose.yml in the root directory of your folder.

version: "3.9"

services:
    app:
        container_name: app
        image: app
        build:
            context: .
            dockerfile: Dockerfile
        restart: always
        ports:
            - "8080:8080"

Let's break down what's happening in this file. We are defining a service called app, that runs the image app with container name app. We are telling it to build the image from the Dockerfile file. We are also telling it to use port 8080 to listen for requests and to restart the container if it crashes.

Let's define the Dockerfile.

Dockerfile

Create a file named Dockerfile in the root directory of your folder.

FROM nginx:alpine

WORKDIR /app

COPY . .

COPY ./nginx.conf /etc/nginx/nginx.conf

Let's explain what is going on here, line by line.

FROM nginx:alpine

We are using the FROM command to tell Docker to use the image nginx:alpine. This image comes pre-installed with Nginx, which is what we want.

WORKDIR /app

This tells Docker to use the /app directory as the working directory. This is where we will eventually copy our files to.

COPY . .

This tells Docker to copy the contents of the . directory into the /app directory. This is how we pass the static files we want to serve to the container.

COPY ./nginx.conf /etc/nginx/nginx.conf

This tells Docker to copy the nginx.conf file into the /etc/nginx/nginx.conf file. This is how we can configure Nginx when it runs inside the Docker container.

Serving Static Files

Now that we have our static files, Nginx configured, and Docker configured, we can run the Docker container and start serving our static website. To deploy the container, use Docker Compose.

docker compose up --build

On the first build, you don't need the build flag, but you will in subsequent runs. If successful, you should see something like this:

The Docker Compose output.

Your static folder and all of its contents are now being served at http://localhost:8080/ using Nginx running inside Docker.

Our static files being served on port 8080.

You can confirm the container is running in Docker, along with all of the other containers that are running by using the docker ps command.

docker ps
CONTAINER ID IMAGE COMMAND                CREATED        STATUS        PORTS                  NAMES
ba804e8bff5f app   "docker-entrypoint.s…" 5 seconds ago  Up 5 seconds  0.0.0.0:8080->8080/tcp app

You can stop the running container by then running docker compose down.

Deploying to Production

Now that your static app has been containerized successfully, it is ready to be deployed to whatever environment you want. This tutorial showed how to deploy it on your own machine, however, this Docker container can be deployed on a staging environment, remain local, or be deployed to a production environment.

To deploy it to production, you will need some kind of server or hosting platform to host the app. There are several different options for hosting, each with their pros and cons. In addition, if your app is a web app, it will likely need a domain as well. Either way, containerizing your static app using Docker is becoming the industry standard and it will certainly help you get your app accessible to your users.

Conclusion

In this tutorial, we used Docker to containerize our static app. We used Docker Compose to run the container and configure it. We also used Nginx to serve the static files. Docker is a powerful tool for a developer to learn and use. As you saw, with just a few lines in your Dockerfile, you can set up a full-blown Nginx instance. This makes deploying the app anywhere you want a breeze. I hope this tutorial has helped you get a better understanding of Nginx, Docker and Docker Compose. Happy deploying!

Resources

  1. Docker
  2. Docker Compose docs
  3. Nginx
  4. Official Nginx Docker Image
Recommended Tutorial »
Copyright © 2017 - 2024 Sabe.io. All rights reserved. Made with ❤ in NY.