Introduction

Up to this point, I hadn’t used Docker very much. The organizations I worked at were traditional Windows environments with no in-house development. I could see the value in containers generally, but it was hard to justify and especially to convince others it was worth using in those environments.

I’ve long hosted various services for myself at home. In the past these were ran on separate Windows VMs so that I could better learn the skills needed for the work I was doing. Looking to make the switch from traditional Systems Administration to DevOps Engineering, it was time to get comfortable with Docker. So, I decided to start running all my home services with it.

Today I’m going over what I did to get the following services running, using Docker:

  • Unifi Controller - network management for Ubiquiti gear
  • PiHole - ad blocker DNS filter
  • WireGuard - VPN

This was all done on a bare metal install of Ubuntu Server.

Installing Docker

I used the official guide to install Docker, following the method to install from their apt repository:

https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

To validate that it’s working, I ran:

sudo docker run hello-world

I also added my user to the docker group, in order to remove the need to preface docker commands with sudo:

sudo usermod -aG docker $USER
newgrp docker

Configuring Docker Compose Files

For each service, I created a folder in my home directory and added a docker-compose.yml file, based on the image creator’s example.

Unifi Controller - /home/rick/unifi/docker-compose.yml:

---
version: "2"
services:
  unifi-controller:
    container_name: unifi-controller
    image: linuxserver/unifi-controller:latest
    environment:
      - PUID=1000 # for UserID
      - PGID=1000 # for GroupID
      - MEM_LIMIT=1024 # Optionally change the Java memory limit (-Xmx) (default is 1024M).
    ports:
      - 10001:10001/udp # Required for AP discovery
      - 8880:8880/tcp # Unifi guest portal HTTP redirect port
      - 8843:8843/tcp # Unifi guest portal HTTPS redirect port
      - 8443:8443/tcp # Unifi web admin port
      - 8080:8080/tcp # Required for device communication
      - 6789:6789/tcp # For mobile throughput test
      - 5514:5514/tcp # Remote syslog port
      - 3478:3478/udp # Unifi STUN port
      - 1900:1900/udp # Required for Make controller discoverable on L2 network option
    volumes:
      - ~/unifi/config:/config # Map a local directory to the container for configuration persistance
    restart: unless-stopped

PiHole - /home/rick/pihole/docker-compose.yml:

---
version: "3"
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 67:67/udp
      - 8888:80/tcp
      - 443:443/tcp
    environment:
      TZ: 'US/Pacific' #this is the time zone
      WEBPASSWORD: 'password'
    volumes:
       - './etc-pihole/:/etc/pihole/'
       - './etc-dnsmasq.d/:/etc/dnsmasq.d/'
dns:
      - 127.0.0.1
      - 1.1.1.1
    restart: unless-stopped

WireGuard - /home/rick/wireguard/docker-compose.yml:

---
networks:
  wireguard:
    name: wireguard

services:
  wireguard:
    container_name: wireguard
    image: lscr.io/linuxserver/wireguard:latest
    ports:
      - 51820:51820/udp
    environment:
      - PUID=1000
      - PGID=1000
      - SERVERURL=auto
      - SERVERPORT=51820
      - PEERS=rickphone
      - PEERDNS=208.67.222.222
      - TZ=US/Pacific
    networks:
      - wireguard
    volumes:
      - /lib/modules:/lib/modules
      - ~/wireguard:/config
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1

Running each Docker Compose file

I didn’t want to have to manually start each container any time the server rebooted, so I created the following script:

UPDATE: I now realize this is unnecessary. The line restart: unless-stopped in each docker-compose.yml file, which i first thought only reloaded an error’d container, also loads the container at system startup. I’m leaving this hack-job script here as a monument to the learning process:

#!/bin/bash
while read service; do
    echo "Starting $service ..."
    docker compose -f ./$service/docker-compose.yml up -d
done < services.txt

with a services.txt file, to easily remove a service if needed later:

unifi
pihole
wireguard

and added the line to crontab using crontab -e, so that it executes at startup:

@reboot sh /home/rick/start-services.sh

Conclusion

Overall, this was a fairly pleasant learning experience. I left out some of the troubles I encountered and details with setting up some of the specifics of each server, but I hope that this helps anyone looking to get their feet wet with Docker.

Cheers!
Rick

 

 


References and Resources

https://learn.cantrill.io/courses/docker-fundamentals

https://github.com/linuxserver/docker-unifi-controller

https://github.com/linuxserver/docker-wireguard

https://github.com/pi-hole/docker-pi-hole