Varnish is an HTTP reverse proxy for accelerating the website that provides dynamic content. WordPress is a blogging system, but the performance is not very good. Docker is a container level virtual machine, it can make developers easily to create and combine different service.
So there is an example for integrating Varnish with WordPress to super speed up your WordPress site.
Here is the Varnish configuration file for WordPress. The source from here. I have modified some config to fit Docker environment.
Path: wordpress-varnish/custom-varnish/wordpress.vcl
# A heavily customized VCL to support WordPress # Some items of note: # Supports https # Supports admin cookies for wp-admin # Caches everything # Support for custom error html page # Assumed 'wordpress' host, this can be docker servicename backend default { .host = "wordpress"; .port = "80"; } sub vcl_recv { # pass wp-admin urls # before any action to fix visual editor disappear if (req.url ~ "(wp-login|wp-admin)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") { return (pass); } # Only a single backend set req.backend_hint= default; # Setting http headers for backend set req.http.X-Forwarded-For = client.ip; set req.http.X-Forwarded-Proto = "https"; # Unset headers that might cause us to cache duplicate infos unset req.http.Accept-Language; unset req.http.User-Agent; # The purge...no idea if this works if (req.method == "PURGE") { if (!client.ip ~ purge) { return(synth(405,"Not allowed.")); } return (purge); } if ( std.port(server.ip) == 6080) { set req.http.x-redir = "https://" + req.http.host + req.url; return (synth(750, "Moved permanently")); } # drop cookies and params from static assets if (req.url ~ "\.(gif|jpg|jpeg|swf|ttf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") { unset req.http.cookie; set req.url = regsub(req.url, "\?.*$", ""); } # drop tracking params if (req.url ~ "\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=") { set req.url = regsub(req.url, "\?.*$", ""); } # pass wp-admin cookies if (req.http.cookie) { if (req.http.cookie ~ "(wordpress_|wp-settings-)") { return(pass); } else { unset req.http.cookie; } } } sub vcl_backend_response { # retry a few times if backend is down if (beresp.status == 503 && bereq.retries < 3 ) { return(retry); } if (bereq.http.Cookie ~ "(UserID|_session)") { # if we get a session cookie...caching is a no-go set beresp.http.X-Cacheable = "NO:Got Session"; set beresp.uncacheable = true; return (deliver); } elsif (beresp.ttl <= 0s) { # Varnish determined the object was not cacheable set beresp.http.X-Cacheable = "NO:Not Cacheable"; } elsif (beresp.http.set-cookie) { # You don't wish to cache content for logged in users set beresp.http.X-Cacheable = "NO:Set-Cookie"; set beresp.uncacheable = true; return (deliver); } elsif (beresp.http.Cache-Control ~ "private") { # You are respecting the Cache-Control=private header from the backend set beresp.http.X-Cacheable = "NO:Cache-Control=private"; set beresp.uncacheable = true; return (deliver); } else { # Varnish determined the object was cacheable set beresp.http.X-Cacheable = "YES"; # Remove Expires from backend, it's not long enough unset beresp.http.expires; # Set the clients TTL on this object set beresp.http.cache-control = "max-age=900"; # Set how long Varnish will keep it set beresp.ttl = 1w; # marker for vcl_deliver to reset Age: set beresp.http.magicmarker = "1"; } # unset cookies from backendresponse if (!(bereq.url ~ "(wp-login|wp-admin)")) { set beresp.http.X-UnsetCookies = "TRUE"; unset beresp.http.set-cookie; set beresp.ttl = 1h; } # long ttl for assets if (bereq.url ~ "\.(gif|jpg|jpeg|swf|ttf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") { set beresp.ttl = 365d; } set beresp.grace = 1w; } sub vcl_hash { if ( req.http.X-Forwarded-Proto ) { hash_data( req.http.X-Forwarded-Proto ); } } sub vcl_backend_error { # display custom error page if backend down if (beresp.status == 503 && bereq.retries == 3) { synthetic(std.fileread("/etc/varnish/error503.html")); return(deliver); } } sub vcl_synth { # redirect for http if (resp.status == 750) { set resp.status = 301; set resp.http.Location = req.http.x-redir; return(deliver); } # display custom error page if backend down if (resp.status == 503) { synthetic(std.fileread("/etc/varnish/error503.html")); return(deliver); } } sub vcl_deliver { # oh noes backend is down if (resp.status == 503) { return(restart); } if (resp.http.magicmarker) { # Remove the magic marker unset resp.http.magicmarker; # By definition we have a fresh object set resp.http.age = "0"; } if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } set resp.http.Access-Control-Allow-Origin = "*"; } sub vcl_hit { if (req.method == "PURGE") { return(synth(200,"OK")); } } sub vcl_miss { if (req.method == "PURGE") { return(synth(404,"Not cached")); } }
Varnish Dockerfile: wordpress-varnish/custom-varnish/Dockerfile
FROM eeacms/varnish COPY wordpress.vcl /etc/varnish/conf.d/wordpress.vcl
Docker-Compose file: wordpress-varnish/docker-compose.yml:
version: "3.4" services: wordpress: image: wordpress:5.1.0-php7.3-apache depends_on: - db restart: always volumes: - ./wordpress:/var/www/html logging: options: max-size: 10m varnish: build: context: ./custom-varnish dockerfile: Dockerfile depends_on: - wordpress restart: always ports: - 6081:6081 environment: BACKENDS: "wordpress" BACKENDS_PORT: 80 BACKENDS_PROBE_ENABLED: "false" logging: options: max-size: 10m db: image: mysql:5.7 restart: always environment: MYSQL_ROOT_PASSWORD: wordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress
Run command: docker-compose up –build