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