Finally, we have all the parts in place to start talking about scaling this Blog using containers. The configuration we are going to create looks like this. As you can see, we are going to use a load balancer to be able to redirect the web requests to a possible pool of servers/containers. In this case I use Nginx because it offers great flexibility and is widely known.
I will not create my own docker container with nginx but will reuse the container which https://github.com/jwilder/nginx-proxy created. The container he created has some interesting functionality in relation with docker, but later more about that.
First, I will set up the configuration using the official nginx docker image dockerfile/nginx
but before I start that I need to change my existing fig configuration to start another Ghost container.
As you can see, I have just added another ghost entry using almost the same parameters. The only difference is in the port mapping, we need to use different ports on the host side.
Now we are going to add the new nginx container which is going to be load balancer.
I am mapping the exposed volume /var/log/nginx to be able to access the nginx logs and the volume /etc/nginx/conf.d to be able to write the nginx load balancing configuration. In my local conf folder I create a ghost.conf file with the following contents:
This is nginx specific configuration which defines the two Ghost web servers in the upstream section and the server section links the base of the request /
to the upstream configuration.
[server1address] and the [server2address] need to be replaced with the actual ip address and port of both containers. We retrieve them using:
If we do the same for the other container we are able to enter both ip addresses in the ghost.conf, which now looks like this.
If we restart nginx inside the nginx container the system is up and running.
But as we already saw in fiddling with fig, restarting containers also assigns new ip addresses to the container. Therefore the current solution and configuration work but is not really maintenance friendly.
Lucky for me, Jason Wilder already created a special nginx-proxy container that is very flexible.
The nginx-proxy container runs nginx and docker-gen. Docker-gen automatically generates reverse proxy configurations for nginx. But also automatically reloads nginx when containers are started and stopped. Really cool!
Docker-gen uses the Docker remote API to inspect the containers IP, Port and other configuration data. The Docker remote API also provides events can can be captured when containers are started or stopped. If you are interested in the source, docker-gen is written in Go and is open-source.
The nginx-proxy automatically enumerates all the containers that have an environment variable set called VIRTUAL_HOST
. There we have to change our fig configuration to include the VIRTUAL_HOST
to the environment variables.
I tried to use fig together with nginx-proxy but when started using fig it seem to not find the docker container events. Therefore, I switched back to my existing bash files to start the containers.
I have 3 bash script files
For starting PostGreSQL
Another one for starting Ghost with the setting of the environment variable that nginx-proxy uses.
And finally one for nginx-proxy
The really nice thing with this setup is that I can start or stop Ghost containers with the Ghost script and they are automatically added to the pool of webservers in the Nginx configuration.
I still don’t know why starting all containers with fig is not working. But I am sure that I will figure it out later.