Building Nginx on Alpine Image for Docker Swarm with Caching Enabled Config

In this guide, we will be creating a nginx reverse proxy with the ability to cache static content using a alpine image.

We will then push the image to gitlab's private registry, and then run the service on docker swarm.

Current File Structure:

$ find .


FROM hypriot/rpi-alpine-scratch  

RUN apk update && \  
    apk add nginx && \
    rm -rf /etc/nginx/nginx.conf && \
    chown -R nginx:nginx /var/lib/nginx && \
    rm -rf /var/cache/apk/*

ADD nginx.conf /etc/nginx/  
ADD conf.d/blog.conf /etc/nginx/conf.d/


CMD ["nginx", "-g", "daemon off;"]  


user nginx;  
worker_processes 1;

events {  
    worker_connections 1024;

error_log  /var/log/nginx/nginx_error.log warn;

http {

    sendfile          on;
    tcp_nodelay          on;

    gzip              on;
    gzip_http_version 1.0;
    gzip_proxied      any;
    gzip_min_length   500;
    gzip_disable      "MSIE [1-6]\.";
    gzip_types        text/plain text/xml text/css

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    error_log   /var/log/nginx/error.log;

    proxy_cache_path /var/cache/nginx/ levels=1:2 keys_zone=nginx_cache:5m max_size=128m inactive=60m;

    keepalive_timeout  60;
    server_tokens      off;

    include /etc/nginx/conf.d/*.conf;


Hostname resolution to our Ghost Blog Service:

In our swarm we have a service called blog which is associated to the docknet network, so the dns resolution will resolve to the vip of the service. As seen in the figure below:

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                                    PORTS  
nq42a6jfwx3d        blog                replicated          1/1                 alexellis2/ghost-on-docker:armv7  


upstream ghost_blog {  
    server blog:2368;

server {  
    listen 80;

    access_log  /var/log/nginx/blog_access.log  main;
    error_log   /var/log/nginx/blog_error.log;

    location / {

        proxy_cache                 nginx_cache;
        add_header                  X-Proxy-Cache $upstream_cache_status;
        proxy_ignore_headers        Cache-Control;
        proxy_cache_valid any       10m;
        proxy_cache_use_stale       error timeout http_500 http_502 http_503 http_504;

        proxy_pass                  http://ghost_blog;
        proxy_redirect              off;

        proxy_set_header            Host $host;
        proxy_set_header            X-Real-IP $remote_addr;
        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header            X-Forwarded-Host $server_name;

Building the Image and Pushing to Gitlab:

$ docker login
$ docker build -t .
$ docker tag
$ docker push

Create the Nginx Reverse Proxy Service on Docker Swarm:

$ docker service create --name nginx_proxy \
--network docknet \
--publish 80:80 \
--replicas 1 \

Listing our Services:

docker service ls  
ID                  NAME                MODE                REPLICAS            IMAGE                                                    PORTS  
je7x21l7egoh        nginx_proxy         replicated          1/1          *:80->80/tcp  
nq42a6jfwx3d        blog                replicated          1/1                 alexellis2/ghost-on-docker:armv7  

Have a look at the benchmark performance when using Nginx with caching enabled