Running Pihole using Docker on your Mac

A colleague of mine mentioned an open source program called Pi-hole designed to act as a DNS resolver in your local network to blackhole trackers and ads. The biggest advantage of this is that it can also be used by devices that don’t support adblockers natively or are cumbersome to use.

So how does one trial something on their local Mac to see if it’s worthwhile? Turns out the project has a Dockerfile and it works quite well, and if you don’t expose the DHCP ports you can ignore breaking your work network with a rogue DHCP server. So assuming you already have Docker installed:

cat <<EOF | tee ~/.piholeenv

docker pull pihole/pihole

docker run -d -p 80:80 -p 53:53 -p 53:53/udp -p 443:443 --restart=unless-stopped --env-file ~/.piholeenv --name pihole pihole/pihole


Next, set your DNS server to

networksetup -setdnsservers Wi-Fi

And nada, a quick, dirty, and SUPER ephemeral test that doesn’t mess with the current DHCP setup on your network. If you want to run it more long term, follow the docs properly and specify a volume to save the data.

To shut it all down:

docker stop pihole
docker rm pihole

Unfortunately my home router provided by my ISP doesn’t offer the ability to change DNS. So I guess that’s the push necessary to get around to putting it in bridge mode and getting a proper router.

Trying to make sense of when to use Docker vs. LXC

While working on some side projects the past couple weeks I kept confusing myself on how things worked behind the scenes between Linux Containers and Docker. They both leverage the Linux kernel’s cgroups to function on Linux (and in Docker’s case - similiar technologies in other OSes), but differ completely in terms of how you interact with them.

While Linux Containers can best be thought of a super lightweight VM to run a whole VM, Docker contains a slew of other features that blur the lines between it acting like a super lightweight VM and being a full platform to build off of. Docker plays closer to the idea of a process/group of processes (application) under a chroot versus LXC’s idea of a whole OS/machine in a chroot jail.

So it’s misleading to think of a Docker container the same way as a LXC container. Same technology behind the scenes but completely different approaches. For Docker it’s all in how you set up your container to run - you can have all the other services you normally get in a VM if you so wish.

For example with LXC setting up MySQL would consist of making the container, running the command to install MySQL and setting the service to go. You can then log in or attach and run other commands as well if necessary.

Docker on the other hand involves similar steps with the flexibility of having Docker do the install and run the service when the container starts (defined in the Dockerfile). However if you want to attach to that container and run more commands you have to have set access to do that up ahead of time (eg. supervisord, runit), create a new container with that command, or try and force your way into the container. (you can try lxc-attach but if you want a new TTY and you’re attaching to a mysqld instance? Not going to work)

After figuring that out - the use of Puppet in Docker started to make more sense. Have Puppet configure your image and then save/commit that state or kick off the supervisord process to keep the container “alive”. Docker lends itself more to recreating/iterating whenever a new update is needed over updating settings.

In summary - LXC container is analagous to a VM, while Docker a very supercharged sandbox for running a process or group of processes. Use LXC when you’re wanting a separate “server” without the extra overhead, Docker when you’re wanting to run a “service”.

I also recommend reading the FAQ - primarily the what Docker “adds to LXC”. In the end it’s left me more leery of using Docker - it’s a bit of a paradigm shift I’m not ready to do just yet.

On one last sidenote, IPv6 support also looks like a lot of pain - but not any worse than LXC.