Learning to use Docker has been on my to-do list for a few years now, especially since I wanted to use Gitlab’s CI/CD, which uses Docker to run builds and tests. I happen to own a Raspberry Pi (like almost every developer), and I didn’t know what to do with it.

Also, uj kind of forced me to try it. Thanks to him, I learned a lot!

When I learned that Google Chrome was going to restrict ad-blockers (https://9to5google.com/2019/05/29/chrome-ad-blocking-enterprise-manifest-v3/), I decided to try out Pi-Hole. It was really the occasion to test Docker at the same time, and so I got to it.

Choosing the right OS#

There are a few choices of OS to pick from to use a RPI as docker host:

While BalenaOS and Hypriot are really focused on dockerizing applications on a RPI, I chose Raspbian, as an easy and versatile approach.

Running Pi-Hole#

Simply put, Pi-Hole is a DNS ad-blocker. What it does is “blocking” HTTP request according to the URL. A DNS (Domain Name System) is a server (listening on port 53 TCP/UDP) which translates a URL to an IP address. So when requesting for an URL (e.g. shittyad.example.com), the DNS server will check if the URL is in the blacklist. If the URL is not in the blacklist, it will simply forward the request to a DNS “above”, like Google’s 8.8.8.8 or Cloudflare’s 1.1.1.1. If the URL is in the blacklist, it will return an error saying that the IP address could not be found. In Chrome, it looks like this :

DNS error in Chrome

So Pi-Hole will not remove blocks of advertisement in your web browser, like what ad-blockers add-ons do, but it will instead not display the ad.

Managing containers#

To manage containers running on my RPI, I ran another container: Portainer. Using the web interface, you can see the logs from each of your running containers, as well as access the terminal inside the containers. There are a bunch of other features, like managing your images, clusters, etc.

To organize these servers, I decided to use Docker Compose, as proposed by a friend. The following draft is what resulted from this decision.

version: '3'

services:
  
  ###### PORTAINER #####
  # Docker manager GUI #
  portainer:
    container_name: portainer
    image: portainer/portainer
    ports:
      - 9000:9000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer:/data
    networks:
      - servers
    restart: unless-stopped

  ##### PIHOLE #####
  # Ad-blocker DNS #
  pihole:
    container_name: pihole
    image: pihole/pihole:4.3_armhf # Docker image of the Pi-Hole server (for RPI)
    ports:
      - 8000:80/tcp # HTTP
      - 8443:443/tcp # HTTPS
      - 53:53/tcp # DNS
      - 53:53/udp # DNS
    volumes:
      - pihole-dns:/etc/dnsmasq.d
      - pihole-data:/etc/pihole
    env_file:
      - ./environment/pihole.env # environment variables set inside the container
    networks:
      - servers
    restart: unless-stopped

volumes:
  portainer:
  pihole-dns:
  pihole-data:

networks:
  servers: