Dockerize Everything

Written by

Subscribe

Introduction

Since I installed Webmentiond on docker and later Wallabag, I have decided to move Miniflux and also host Bitwarden myself, everything on Docker.

The other services I have on my server is a Wordpress Blog and three static sites. Before the switch my setup was as follows.

  1. Nginx server in front of everything, with the help of Certbot to manage ssl.
  2. Wordpress blog working with PHP-FPM and Nginx, of course MySQL running on the server.
  3. Miniflux installed on the server using PostrgreSQL (it was already running on the server because Mastodon used to be in that server)
  4. The static sites were hosted by Nginx, and all 404 errors were sent back to Apache to handle them as redirections with an .htaccess file.

The idea was to have a bare Linux host with everything working on Docker containers.

The services

Wordpress

I started with Wordpress, and it was actually the hardest part, I have discovered that Wordpress does not like to be behind a proxy. But first things first, I am using the official Wodpress image that works with Apache and it is supposed to expose port 80, but I want to have other applications running on the same server, so I needed it to run behind a proxy.

The way I managed to do it, was using this Docker Compose file

version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8000:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
      WORDPRESS_CONFIG_EXTRA: |
        define('WP_HOME', 'https://my-site');
        define('WP_SITEURL', 'https://my-site');
        define('FORCE_SSL_ADMIN', true);

    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

The important lines are those extra configuration lines, that define the Home url, Site url, and the one that force SSL on the Admin interface, because I plan to use SSL with that site. Those lines add the extra configuration to wp-config.php file. Seems easy, but it took me a lot of time to figure it out.

I prefer to run a vanilla WordPress installation, so I try to avoid the installation of plugins, even the cache ones. But if the the site gets a lot of visits out of a sudden, it will not be able to handle them, so I have also installed Varnish as another Docker container. The important part of the default.vcl file is:

backend server1 { # Define one backend
  .host = "public.ip.of.my.server";    # IP or Hostname of backend
  .port = "8000";           # WodPress container port
  .max_connections = 300; # That's it

And to start Varnish I have this Docker Compose file.

version: '3.3'
services:
    my-varnish:
        build: .
        container_name: my-running-varnish
        restart: always
        tmpfs: '/var/lib/varnish:exec'
        ports:
            - '7000:80'
        image: my-varnish

And the Dockerfile is:

FROM varnish:6.2
COPY default.vcl /etc/varnish/

All those files should be on the same folder, that is it for WordPress, it is working now.

Bitwarden

This one is easy, as it is designed to work in a Docker container, so I only followed the instructions and have it working.

By the way, it is really important to host your own passwords, as you should trust nobody to manage them.

Miniflux

Miniflux is supposed to be installed directly on the host server, and not on Docker, but there is an option documented for that, you can find it here. It was not difficult to have it running.

Then I only needed to export my opml file from the old server, change the DNS server to point the new one and upload it there.

Wallabag

Wallabag also have an example to run it with Docker, but the example for Docker Compose file works with MySQL, I think that is not needed, so I modified that a little, and this is the one I am using.

version: '3'
services:
  wallabag:
    image: wallabag/wallabag
    restart: always
    environment:
      - SYMFONY__ENV__MAILER_HOST=smtp.server.com
      - SYMFONY__ENV__MAILER_USER=postmaster@my-site
      - SYMFONY__ENV__MAILER_PASSWORD=my-strong-pass
      - SYMFONY__ENV__FROM_EMAIL=postmaster@my-site
      - SYMFONY__ENV__DOMAIN_NAME=https://my-wallabag-site
      - SYMFONY__ENV__FOSUSER_REGISTRATION=false
    ports:
      - "8383:80"
    volumes:
      - images:/var/www/wallabag/web/assets/images
      - data:/var/www/wallabag/data
  redis:
    image: redis:alpine
volumes:
  images:
  data:

With this Docker Compose file, my Wallabag uses SQLite instead of MySQL.

Webmention

Webmention is the reason I have decided to go full Docker for my self hosted services. It was not easy the first time, but with the kind help of Horst and Yarmo I have it working now.

This is the only one service not working with a Docker Compose file, as I was not able to pass some commands to the container using docker-compose instead of docker run command. I think I will manage to solve that later.

Caddy server

Last by not least there is the need to have a reverse proxy in order to serve all other apps to the public or at least to me, I do not want to have to remember each port, and also I need something to serve the static sites.

I could have chosen Nginx which is the default option for reverse proxy, but I wanted to learn something new, and Caddy 2 has just released so I wanted to give it a try.

Because the distribution I am using as host is Arch Linux, and the Caddy version that comes with it is 1, and because everything was on Docker, I have decided to have Caddy also on Docker, it was not planned that way, but I thought it was a good idea at the end.

I am using Docker Compose once again.

version: '3.3'
services:
    caddy:
        restart: always
        ports:
            - '80:80'
            - '443:443'
        volumes:
            - '/var/www:/usr/share/caddy'
            - 'caddy_data:/data'
            - 'caddy_config:/config'
            - '/home/ggarron/docker-hub/caddy/caddy.conf:/etc/caddy/Caddyfile'
        image: 'caddy:2.1.1-alpine'
volumes:
  caddy_data:
  caddy_config:

Now I do not have to worry about ssl, Caddy takes care of the certificates for all sites for me, and does a great job as a reverse proxy and as a web server too.

I have used Apache ab tool to do some test on the static site with both Nginx and Caddy, the result was better on Caddy, slightly better. 84 pages per second on Nginx vs 90 page per second on Caddy.

Conclusion

I am now happy with my new configuration, specially because it will be now easier to test any new app, and then just delete its container, of course this is less efficient than running the apps directly on the server, but for the load I put on the server, that is not an issue.

Also, having the Docker Compose files, and the configuration files, is really easy to move from one VPS provider to a new one in case I need to do it.

I will keep my old Ubuntu 18.04 server for a couple of days, and then I will delete it. My Mastodon instance runs on its own server yet, but I am thinking in dockerize it and move it to this server.