Wrestling with Docker
For years I have been running a blog and other web apps on a VPS running Ubuntu
14.04 and Apache - a standard
LAMP system. However,
after experimenting with some apps - temporarily installing them and testing
them, only to discard them, the system was becoming a total mess. Worst of all,
various MySQL files were ballooning out in size: the
ibdata1 file in
/var/lib/mysql was coming in at a whopping 37Gb (39568015360 bytes to be more accurate).
Now, there are ways of dealing with this, but I don't want to have to become an expert in MySQL; all I wanted to do was to recover my system and make it more manageable.
I decided to use Docker. This is a "container system" where each app runs in its own container - a sort of mini system which contains all the files required to serve it up to the web. This clearly requires a certain amount of repetition between containers, but that's the price to be paid for independence. The idea is that you can start or stop any container without affecting any of the others. For web apps many containers are based on Alpine Linux which is a system designed to be as tiny as possible, along with the nginx web server.
There seems to be a sizable ecosystem of tools to help manage and deploy docker containers. Given my starting position of knowing nothing, I wanted to keep my extra tools to a minimum; I went with just two over and above docker itself: docker-compose, which helps design, configure, and run docker containers, and traefik, a reverse proxy, which handles all requests from the outside world to docker containers - thus managing things like ports - as well as interfacing with the certificate authority Lets Encrypt.
My hope was that I should be able to get these all set up so they would work as happily together as they were supposed to do. And so indeed it has turned out, although it took many days of fiddling, and innumerable questions to forums and web sites (such as reddit) to make it work.
So here's my traefik configuration:
defaultEntryPoints = ["http", "https"] [web] address = ":8080" [web.auth.basic] users = ["admin:$apr1$v7kJtvT7$h0F7kxt.lAzFH4sZ8Z9ik."] [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [traefikLog] filePath="./traefik.log" format = "json" # Below here comes from # www.smarthomebeginner.com/traefik-reverse-proxy-tutorial-for-docker/ # with values adjusted for local use, of course # Let's encrypt configuration [acme] email="firstname.lastname@example.org" storage="./acme.json" acmeLogging=true onHostRule = true entryPoint = "https" # Use a HTTP-01 acme challenge rather than TLS-SNI-01 challenge [acme.httpChallenge] entryPoint = "http" [[acme.domains]] main = "numbersandshapes.net" sans = ["monitor.numbersandshapes.net", "adminer.numbersandshapes.net", "portainer.numbersandshapes.net", "kanboard.numbersandshapes.net", "webwork.numbersandshapes.net", "blog.numbersandshapes.net"] # Connection to docker host system (docker.sock) [docker] endpoint = "unix:///var/run/docker.sock" domain = "numbersandshapes.net" watch = true # This will hide all docker containers that don't have explicitly set label to "enable" exposedbydefault = false
and (part of) my docker-compose configuration, the file
version: "3" networks: proxy: external: true internal: external: false services: traefik: image: traefik:1.6.0-alpine container_name: traefik restart: always command: --web --docker --logLevel=DEBUG volumes: - /var/run/docker.sock:/var/run/docker.sock - $PWD/traefik.toml:/traefik.toml - $PWD/acme.json:/acme.json networks: - proxy ports: - "80:80" - "443:443" labels: - traefik.enable=true - traefik.backend=traefik - traefik.frontend.rule=Host:monitor.numbersandshapes.net - traefik.port=8080 - traefik.docker.network=proxy blog: image: blog volumes: - /home/amca/docker/whats_this/public:/usr/share/nginx/html networks: - internal - proxy labels: - traefik.enable=true - traefik.backend=blog - traefik.docker.network=proxy - traefik.port=80 - traefik.frontend.rule=Host:blog.numbersandshapes.net
The way this works, at least in respect of this blog, is that files copied into
/home/amca/docker/whats_this/public on my VPS will be
automatically served by nginx. So all I now need is a command on my local
system (on which I do all my blog writing), which serves up these files. I've
hugo -b "https://blog.numbersandshapes.net/" -t "blackburn" && rsync -avz -e "ssh" --delete public/ email@example.com:~/docker/whats_this/public
Remarkably enough, it all works!
One issue I had at the beginning was that my original blog was served up at the
https://numberdsandshapes.net/blog and for some reason these links were
still appearing in my new blog. It turned out (after a lot of anguished
messages) that it was my mis-handling of
rsync. I just ended up deleting
everything except for the blog source files, and re-created everything from scratch.