DEV Community

vuong ⛈️
vuong ⛈️

Posted on • Updated on

Dockerization: Varnish, Nginx & try to hit the first cache

Introduction

Varnish help to decreases directly request to the web server by cache response after first-time response, help your website perform better. You can make the configuration for caching-path, what you want to ignore, how to purge/ban cache.

I like Docker, I run my website on Docker, multiple services by Docker-Compose, I’m just a developer, no more knowledge about the system like a DevOps, I want to make it run by the simple way.

I would like to mention online NGINX and varnish. It’s mean NGINX will cover backend and connect to varnish to handle the response.

Requisites

  • Nginx has covered web and it’s still running before installing varnish
  • Nginx and varnish must be on the same internal network

Notes

  • Nginx will run out with port 8080
  • Varnish will run out with port 80
  • Varnish can’t handle SSL. If you need to handle this protocol, this post can’t help you more
  • Property build: ../nginx-server includes NGINX configuration, you could use the image directly. It should be controlled on your side Property build: ../varnish includes varnish configuration. I will explain only this part

Docker images

Varnish docker image: https://github.com/newsdev/docker-varnish (It has included the way to setting and run docker image, I just write more for docker-compose config)

Nginx: https://hub.docker.com/_/nginx/

Settings

  • Create ../varnish folder
  • Access to created folder and make Dockerfile
FROM newsdev/varnish:4.1.0
ENV VARNISH_MEMORY 100m
Enter fullscreen mode Exit fullscreen mode
  • Create default.vcl in the same folder, it’s varnish configuration
vcl 4.0;
backend default {
  .host = "nginx-server";
  .port = "80";
}

# If you don't include below, header Age in response to client always be 0

sub vcl_deliver {
  # Display hit/miss info
  if (obj.hits > 0) {
    set resp.http.V-Cache = "HIT";
  }
  else {
    set resp.http.V-Cache = "MISS";
  }
  set resp.http.Access-Control-Allow-Origin = "*";
  set resp.http.Access-Control-Allow-Headers = "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With";
  set resp.http.Allow = "GET, POST";
  set resp.http.Access-Control-Allow-Credentials = "true";
  set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, OPTIONS, PATCH";
  set resp.http.Access-Control-Expose-Headers = "X-Pagination-Total, X-Pagination-Page, X-Pagination-Limit";
}
sub vcl_backend_response {
  if (beresp.status == 200) {
    unset beresp.http.Cache-Control;
    set beresp.http.Cache-Control = "public; max-age=200";
    set beresp.ttl = 200s;
  }
  set beresp.http.Served-By = beresp.backend.name;
  set beresp.http.V-Cache-TTL = beresp.ttl;
  set beresp.http.V-Cache-Grace = beresp.grace;
}

Enter fullscreen mode Exit fullscreen mode
  • Modify service’s configuration for docker-compose.yml
version: '2'

networks:
  localnetwork:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 162.11.1.0/24
          gateway: 162.11.1.1
services:

  nginx-server:
    container_name: nginx-server
    build: ../nginx-server
    networks:
      - localnetwork
    ports:
      - "8080:80"
  varnish:
    build: ../varnish
    container_name: varnish
    networks:
      - localnetwork
    ports:
      - "80:80"
    depends_on:
      - nginx-server

Enter fullscreen mode Exit fullscreen mode
  • Build & run Docker
docker-compose build
docker-compose up -d
Enter fullscreen mode Exit fullscreen mode
  • Access URLs and check the headers
http://docker-host-ip:8080/users/{user_id} #Routing to your method, always no cache
http://docker-host-ip/users/{user_id} #Through Varnish first

Enter fullscreen mode Exit fullscreen mode
  • Hit varnish caching URL, and see the Age value in the response headers:
Age = 0, Cache wasn’t HIT (known as MISS)
Age != 0, Cache was HIT (you’re successful)
Enter fullscreen mode Exit fullscreen mode

Helpful commands

# View varnish cache his/miss
docker exec -it varnish bash
varnishncsa -F "%m %U%q ---- %{Varnish:handling}x"
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
rvanlaak profile image
Richard van Laak

Great post! Unfortunately following it for us leads to the following Vagrant error log:

Error:
Message from VCC-compiler:
Expected an action, 'if', '{' or '}'
('input' Line 12 Pos 5)
    setresp.http.V-Cache = "HIT";

----####################----------

Running VCC-compiler failed, exited with 2
VCL compilation failed
Collapse
 
rvanlaak profile image
Richard van Laak

Found out the typos; it should be:

  • set resp instead of setresp
  • unset beresp instead of unsetberesp
  • set beresp instead of setberesp
Collapse
 
vuong profile image
vuong ⛈️

Thanks for catching 😂. I have updated the post 🤗.