Docker is certainly interesting. It adds an additional layer between operating system and application which can be used to ease deployment. So it is somewhere between full blown virtual machines and a simple ‘chroot’. The most memorable description I heard is that ‘Docker is just a fancy wrapper for LXC’.
There are some pitfalls however, coupled with a lot of bad docker-images and even worse tutorials (the kind that only says ‘do X, then Y’) it first turned me off. However, the magic behind it is quite simple, and if you follow some basic guidelines, it is not hard to gain value from using it.
First, treat all data inside containers as not persistent. You will run into a giant headache when you need to upgrade / change an existing container. To bypass this issue, use data volumes to ‘mount’ directories from the container to your host. Now you can remove containers without worrying about your data.
We already can apply the persistent data section when we start up our containers via systemd.
Of course you can just call
docker start and
docker stop in your systemd files, but then we are exactly where we don’t want to be and experience the difficulties mentioned above if you want to upgrade your containers.
There is always bad after taste if you produce unit files which are not self sufficient (you manually need to docker run a container with a matching name, else docker start will fail).
Additionally all parameters you supply to your run command will get ‘lost’ that way if you decide to remove the container.
To work around this we stop and remove the old container and run a new one every time we start the unit.
[winlu@winlu-main system]$ cat docker_nginx_reverse.service [Unit] Description=docker nginx_reverse proxy container After=docker.service Requires=docker.service [Service] Restart=always ExecStartPre=-/usr/bin/docker stop -t 2 nginx_reverse ExecStartPre=-/usr/bin/docker rm nginx_reverse ExecStart=/usr/bin/docker run --rm --name nginx_reverse -p 80:80 -p 443:443 -e DEFAULT_HOST=heroicdebugging.biz -v /docker/nginx_reverse/certs:/etc/nginx/certs -v /docker/nginx_reverse/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy [Install] WantedBy=multi-user.target
=- in the ExecStartPre Lines are to not abort if the command fails.
If you want automatic updates, add another ExecStartPre line pulling the latest image version. I can however only recommend this if you are the person providing the update to the image (i.e. the image is under your control in docker hub).
This is what actually got me interested into trying Docker. It sets up nginx as a reverse proxy. The differentiating feature here is that you can now add other containers and proxy them via an environment variable defining their host name without editing a configuration file manually.
Show me your moves
So if you want to serve
www.heroicdebugging.biz via nginx, you would first set-up nginx-proxy as described on their github README, then add another nginx docker container with the additional variable
docker run -e VIRTUAL_HOST=www.heroicdebugging.biz -d nginx.
As long as
www.heroicdebugging.biz resolves to the docker host IP, it should forward the request to the appropriate container.
This makes it trivially easy to add other subdomains or host other domains on the same host.
vhost specific configurations
Sometimes you don’t want to directly modify the nginx containers you route via nginx-proxy. Sometimes you have to add specific configuration to the forwarding part of the reverse proxy configuration.
To handle those cases you should be using the feature provided by nginx-proxy to mount a
vhosts.d directory on your host.
There you can create configuration files with the name of the
VIRTUAL_HOST which then gets included into the matching server section in the reverse proxy configuration.
error page handling
To catch errors on the reverse proxy level instead of the actual provider of the error you have to add
proxy_intercept_errors to the vhost specific configuration.
So to add a custom 404 page located at the root serving directory with the name 404.html, we need to add the following:
error_page 404 /404.html; proxy_intercept_errors on;
allowing big files
Other uses of the
vhosts.d directory would be to set
client_max_body_size to a higher value to allow something like owncloud to be reverse proxied as well.
redirect to other URL
I want heroicdebugging.biz requests to be forwarded to the www sub domain.
To archive this I started another container with
Finally I just need to add the following snippet to my
heroicdebugging.biz file in the
return 301 https://www.heroicdebugging.biz$request_uri;