A journey static assets web server: Part I

The main idea build this stuffs it’s just for want to learn how Caching works on Nginx because I was read bunch of great articles that’s inspired me like Why Netflix Chose NGINX as the Heart of Its CDN and Serving 100 Gbps from an Open Connect Appliance then suddenly my curious thoughts told me to browse deep about that and I was found cool The 5-hour CDN and this repository .

Okay, because currently only has 1 server and my idea is so naive. I just usually thinking treat it as a nginx –> webserver that server static server like below.

static-sites

Beside this one for fun learning purpose usage, I was wondering what’s I would use for web server of static files ? Do i need used nginx or apache again and treat them as container (like I did usually ?) and yeah the answer is NO!. I need to start find something Awesome web server that can serve static files the uncommon ways.

First it’s like I just want to create it with golang then serve and done, but after that I found article The smallest Docker image to serve static websites and mention about thttpd then let’s try this one!

Enter thttpd

Lets build the container first, prepare the Dockerfile like below, TBH i copycat-ing from this repository .

# For complete version please see:
# https://github.com/emsixteeen/thttpd-container/blob/master/Dockerfile
FROM alpine:3.15 AS builder
ARG THTTPD_VERSION=2.29
# Install all dependencies required for compiling thttpd
RUN apk add gcc musl-dev make
# Download thttpd sources
RUN wget http://www.acme.com/software/thttpd/thttpd-${THTTPD_VERSION}.tar.gz \
    && tar xzf thttpd-${THTTPD_VERSION}.tar.gz \
    && mv /thttpd-${THTTPD_VERSION} /thttpd
# Compile thttpd to a static binary which we can copy around
...

# Switch to the scratch image
...
STOPSIGNAL SIGTERM
# Run thttpd
CMD ["/thttpd", "-D", "-h", "0.0.0.0", "-p", "3000", "-d", "/home/static", "-u", "static", "-l", "-", "-M", "384"]

After build it, I got nice sized container image /lgtm && /approve

...
cedeen_webz    latest    cf5902e2ddb7    10 months ago    188kB
...

Just usual ways to run it and mount the volume that contain your images/static files, here is my example:

datz/
├── images
│   ├── 1.webp
│   ├── ... .webp
│   └── ... .webp
├── index.html
└── robots.txt # IYKYK 🙄
docker run -p 3000:3000 -v $HOME/datz:/home/static ...

Nginx cached mode

In this part it was interesting, probably it’s time to play with caching so let’s dive into it with spawn your vhost conf file and here is my example.

# Tell nginx to create cache data storage with key_zone name "cdn"
# with max cache size 50M
proxy_cache_path /tmp/nginx-cdn levels=1:2 keys_zone=cdn:10m max_size=50M inactive=60m use_temp_path=off;

server {
	...
	# Show header cache status
	add_header X-Cache-Status $upstream_cache_status;
	add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
	...
	# Regex: all file with extension .webp/jpg/jpeg in all path
	location ~* ^.+\.(png|jpe?g)$ {
            # Tell this location to use key_zone
            proxy_cache cdn;
            # Enables revalidation of expired cache
            proxy_cache_revalidate on;
            proxy_cache_min_uses 3;
            proxy_cache_background_update on;
            proxy_cache_lock on;
            # valid for this http status code with x minutes time
            proxy_cache_valid 200 301 302 10m;
            proxy_cache_valid 404 1m;
            # disable this header for cached
            proxy_ignore_headers Cache-Control;
            proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
	}
}

For better visbility any other module please refer Module ngx_http_proxy_module .

Testing

For testing purpose, try request it with curl and make sure to print the header section.

$ curl -LIs https://localhost:3000/images/static-site-ideas.webp
....
content-security-policy: frame-ancestors 'self'
x-dotwell: 384kbps
x-frame-options: SAMEORIGIN
x-cache-status: HIT # Got hitted
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
referrer-policy: strict-origin
cache-control: public, max-age=31536000
...

PS: I try around 3-4 request and got x-cache-status: HIT this triggered by module proxy_cache_min_uses 3;.

Closing thought

Good Reads Sources