Hey, just a heads-up that this content is based on an automatically imported version from our old CMS. If the formatting isn’t perfect, I’m sorry about that.

Title Image: pihole docker with docker-compose in my LAN

Recently I moved from my old PI3B to an Intel NUC i3 as my “Home Server”. It has enough power to run all my local services and is still not wasteful in terms of power consumption and space requirement like a “real” Server, and it is fanless.

Due to the gained CPU Power and a bit more flexibility over my previous used pfBlockerNG, I decided to give Pi-hole a try. If you do not know Pi-hole, in short: A local GUI Managed Filtering DNS Cache using Blocklists to block Malware/Ads/Phishing/… you could say a “uBlock Origin” server-based.

Docker-compose and Pi-hole

Instead of running Pi-hole directly on my Ubuntu LTS, I decided to go the Docker way, which should give me an easier way to update it. Instead of the “manual” Docker way, I prefer to go with docker-compose. That’s a tool for easily managing, upgrading, and deploying Docker containers/images by just one config file. So what you need to do is actually very simple. First, install Docker and docker-compose packages on your system. In Ubuntu, this is:

apt update
apt install docker docker-compose

Docker-compose is handling everything for you; the only thing you need to tell it is what to do exactly in a YML config. This is mine:

version: "3"
# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "67:67/udp"
      - "80:80/tcp"
      - "443:443/tcp"
    environment:
      TZ: 'Europe/Berlin'
      # WEBPASSWORD: 'set a secure password here or it will be random'
      WEBPASSWORD: 'yourTopSecretPassword!'
      INTERFACE: 'eno1'
      DNSMASQ_USER: 'pihole'
    # Volumes store your data between container upgrades
    volumes:
      - './etc-pihole/:/etc/pihole/'
      - './etc-dnsmasq.d/:/etc/dnsmasq.d/'
    # first always should be 127.0.0.1 the second here should be your router or
    # a public available DNS. Those are not your pihole upstream servers later used!
    # The pihole upstream servers can be configured in the GUI Later.
    dns:
      - 127.0.0.1
      - 1.1.1.1
    # Recommended but not required (DHCP needs NET_ADMIN)
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    cap_add:
      - NET_ADMIN
      - CAP_NET_BIND_SERVICE
      - CAP_NET_RAW
    restart: unless-stopped

So, to get started, it’s best to create a new user named pihole and in its home directory, create the above docker-compose.yml. After that, make sure you are in the same directory (cd /home/pihole) and you can install everything with the command:

docker-compose up

You should now see docker-compose downloading and installing the new container and spawning it. When it’s done, check the Pi-hole admin interface at /admin in your web browser and use the previously set password to log in. If everything works as intended, you can use your Pi-hole local IP as the DNS server for your clients. In my case, I do not use Pi-hole’s DHCP Server feature. Instead, I let my router (pfSense) distribute my Pi-hole’s IP as DNS to my LAN clients and created some rules to forbid all other tcp/udp Port 53 outgoing traffic for LAN clients, with the exception of the Pi-hole itself.

To start it in the background, you can use the docker-compose start command. Also, make sure that Docker itself is auto-started after boot by systemctl enable docker. Useful is the command docker-compose logs to see the recent logs of the composer and container.

Another useful thing is adding an alias to your bash aliases. If you run Pi-hole without a container, you can use the pihole command to see the live log or issue some commands like adding whitelist entries from CLI and so on. In a Docker container, you can’t run the pihole binary just in the CLI; you need to run it through docker exec. As a shortcut, you can add this to your ~/.bash_aliases:

alias pihole='docker exec pihole pihole $@'

After relogging into your shell, you now have the direct Pi-hole CLI available. For example, you can now tail the Pi-hole live log with pihole -t.

So basically, that’s it. Having a Pi-hole running in 5 minutes. The next thing to add is full internal IPv6 support.

Update: I was asked what lists I can recommend for Pi-hole. Well, that is a very personal decision. Most people do not need the China List, for example, but because we use a lot of Chinese websites here, it is a welcome addition for me. I can only give one tip: whatever lists you choose, have a look that they are regularly maintained and old, non-existing hosts are removed. Here is a gist with my current (tbc) used Lists.

How to update Pi-hole Docker?

Due to your config being saved outside the actual container, it is really just a pull, stop, and run. Very simple, no headache.

docker pull pihole/pihole
docker-compose down
docker-compose up -d