Maximum speed up for HTTP/2 in one place

As you know there are several ways to speed up your website like:
– HTTP/2
– Brotli compression
– Webp image format
– HTTP Caching

but they are still separate. There is no one ready solution that would unite them all.

Lets try to combine all we need in one place!

Many companies operate their websites on Cloud providers and we need our solution to be cloud friendly.
For example Amazon AWS have Amazon ECS service based on docker and i will try to combine all functionality in 1 docker container.

It will be very convenient to use Docker Registry and scale it for any needs.

So we need:

– All requests to our website go to HTTP/2 endpoint with server push support
– All javascript/css/html requests are served using Brotli compression
– Images are packed using Webp where possible
– Responses from our origin should be cached and served from cache where possible to reduce the load of application instances

The ideal structure is presented below:

Lets sort it out:

– Docker container binds to 80 and 443 ports and /etc/ssl mountpoint to get SSL certificate and secure HTTP traffic.
– For SSL termination and HTTP/2 implementation lets use Caddy as it can operate QUIC/39 proto and HTTP/2 out of the box
– For caching responses lets use Varnish. Varnish is the most convenient solution for caching. But Varnish can operate only with http (not https) backends
– Thats why lets use Nginx for Brotli compression and Webp converting on-fly from any kind of HTTP protocol of origin backend.
– Supervisord should be entrypoint on docker run and should recover any internal application in case of crashing/stopping.

We can use all Docker power to build container and run it on every instance just in one command.

So lets start:

Dockerfile:

FROM amazonlinux:2

RUN yum -y update
RUN yum -y install mc gcc telnet nc wget tar gzip git hostname systemd sudo dbus initscripts
RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -P /tmp
RUN yum install -y /tmp/epel-release-latest-7.noarch.rpm
RUN yum install -y caddy supervisor nginx libwebp libwebp-tools
RUN amazon-linux-extras install php7.2
#i`d like to use my own pre-compiled Varnish as it contains Maxmind GeoIP2 module.
RUN cd /tmp && git clone https://github.com/vladbondarenko/varnish-5.2.1
#remove some unused files for Docker
RUN rm -rf /tmp/varnish-5.2.1/etc/init.d
RUN cp -r /tmp/varnish-5.2.1/etc/* /etc/
RUN cp -r /tmp/varnish-5.2.1/usr/* /usr/
RUN echo “127.0.0.1 http2.internal” >> /etc/hosts
RUN echo “http2.internal” > /etc/hostname
RUN ldconfig
RUN mkdir -p /usr/local/var/varnish/ && chmod 777 /usr/local/var/varnish/
#copy config files for all services
COPY varnish.ini /etc/supervisord.d/
COPY caddy.ini /etc/supervisord.d/
COPY caddy.conf /etc/caddy/
COPY nginx.conf /etc/nginx/
COPY nginx.ini /etc/supervisord.d/
COPY default.vcl /etc/varnish/
COPY php.ini /etc/supervisord.d/
#copy binaries
COPY caddy /bin/caddy
COPY brotli /bin/brotli
RUN mkdir -p /var/www
#copy webp/brotli related scripts
COPY brotli.php /var/www
COPY webp.php /var/www
COPY start.sh /
RUN chown nginx:nginx /var/www/*
RUN ulimit -n 16384
#start supervisord
CMD /start.sh

Other files could be found at https://github.com/vladbondarenko/http2-proxy

And all we need is to run container:

docker run –name http2 -d -p 443:443 -p 80:80 -v /etc/ssl:/etc/ssl –env DOMAIN=test.test.com –env PROTO=http –env ORIGIN=2.2.2.2 –env PORT=8080 –hostname http2.internal http2

Have fun!