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.
- Visit the official Docker website to get the installer.
- After it downloads, run the installer until the end.
- 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:
BASHapp
├── 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:
HTML<!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:
BASHevents {
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.
YMLversion: "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.
DOCKERFILEFROM nginx:alpine
WORKDIR /app
COPY . .
COPY ./nginx.conf /etc/nginx/nginx.conf
Let's explain what is going on here, line by line.
DOCKERFILEFROM 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.
DOCKERFILEWORKDIR /app
This tells Docker to use the /app
directory as the working directory. This is where we will eventually copy our files to.
DOCKERFILECOPY . .
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.
DOCKERFILECOPY ./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.
BASHdocker 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.
BASHdocker ps
BASHCONTAINER 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
- Getting Started with TypeScript
- Getting Started with Solid
- Getting Started with Express
- How to build a Discord bot using TypeScript
- How to deploy a PHP app using Docker
- How to deploy a MySQL Server using Docker
- Using Puppeteer and Jest for End-to-End Testing
- Getting Started with Moment.js
- Creating a Twitter bot with Node.js
- Building a Real-Time Note-Taking App with Vue and Firebase
- Getting Started with Vuex: Managing State in Vue
- Using Axios to Pull Data from a REST API