Creating a simple Nginx-based web server image

One of the hardest parts of blogging is identifying topics. I sometimes struggle with identifying things that I have done that would be interesting or helpful to others. In trying to establish a “rule of thumb” for such decisions, I think things that I have done at least twice qualify as potential topics. As it so happens, I have had to construct simple web server containers twice in the last few weeks.

The Problem

Very simply, I wanted to be able to build a quick and painless container to host some static web sites. They are mostly demo sites for some of the UI libraries that we have been building. One is raw HTML, the other is built using Storybook.js, but both end up being a set of HTML/CSS/JS files to be hosted.


The requirements for this one are pretty easy:

  • Host a static website
  • Do not run as root

There was no requirement to be able to change the content outside of the image: changes would be handled by building a new image.

My Solution

I have become generally familiar with Nginx for a variety of uses. It serves as a reverse proxy for my home lab and is my go-to ingress controller for Kubernetes. Since I am familiar with its configuration, I figured it would be a good place to start.

Quick But Partial Success

The “do not run as root” requirement led me to the Nginx unprivileged image. With that as a base, I tried something pretty quick and easy:

# Dockerfile
FROM nginxinc/nginx-unprivileged:1.20 as runtime

COPY output/ /usr/share/nginx/html

Where output contains the generated HTML files that I wanted to host.

This worked great for the first page that loaded. However, links to other pages within the site kept coming back from Nginx with :8080 as the port. Out networking configuration is offloading SSL outside of the cluster and using ingress within the cluster, so I did not want any port forwarding at all.

Custom Configuration Completes the Set

At that point, I realized that I needed to configure Nginx to disabled the port redirects, and then include the new configuration in my container. So I trapsed through the documentation for the Nginx containers. As it turns out, the easiest way to configure these images is to replace the default.conf file in /etc/nginx/conf.d folder.

So I went about creating a new Nginx config file with the appropriate settings:

server { 
  listen 8080;
  server_name localhost;
  port_in_redirect off;
  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
  error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;

From there, my Dockerfile changed only slightly:

# Dockerfile
FROM nginxinc/nginx-unprivileged:1.20 as runtime
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY output/ /usr/share/nginx/html


With those changes, the image built with the appropriate files and the links no longer had the port redirect. Additionally, my containers are not running as root, so I do not run afoul of our cluster’s policy management rules.

Hope this helps!






Leave a Reply

Your email address will not be published. Required fields are marked *