Setting Up a Pihole Docker¶
For some easy-listening learning, I often turn to NetworkChuck's YouTube channel. Recently, I decided to set up Pi-hole, a network-wide ad and tracker blocking application that acts as a DNS sinkhole and optionally as a DHCP server. However, Chuck's video used a Pi-hole image that wasn't ARM architecture compatible. I modified it, pulled the regular pihole/pihole:latest image, and then watched Brandon Lee's VirtualizationHowTo channel for additional insights. Here are my notes from this process:
Option 1: Create the Pihole Container¶
docker run -dit -p 53:53/tcp -p 53:53/udp -p 80:80 -p 443:443 -v "$(pwd)/etc-pihole:/etc/pihole:z" -v "$(pwd)/etc-dnsmasq.d:/etc/dnsmasq.d:z" --name chacho_pihole pihole/pihole:latest
chacho_pihole
.
2. Port forwarding is set up so the host forwards traffic to the Pi-hole container. Note: On macOS, mDNSResponder may use port 53 (and possibly 5353). In that case, use an alternative port like 5399 for the host while keeping port 53 for the container.
3. We are mounting two volumes from the current working directory to the container's directories.
Once this container is spun up, and in a healthy status (docker ps
to check this), we're ready to visit the Pi-hole interface. Open up a browser and use your docker host IP address like so:
http://10.2.3.4/admin
Option 2: Configure docker-compose.yaml¶
The benefit of this method is being able to configure SSL using a Traefik container in conjunction with the Pi-hole container.
mkdir pihole && cd pihole && nano docker-compose.yaml
version: '3.3'
services:
traefik2:
image: traefik:latest
container_name: traefik
restart: always
ports:
- "80:80" # The HTTP port
- "443:443" # The HTTPS port
networks:
- traefik
volumes:
- "/var/run/docker.sock:/var/run/docker.sock" # So Traefik can listen to Docker events
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
pihole:
image: pihole/pihole:latest
container_name: chacho-pihole
restart: always
ports:
- "5380:53/tcp"
- "5380:53/udp"
dns:
- 208.67.220.220
- 208.67.222.222
environment:
TZ: 'America/New York'
WEBPASSWORD: 'AdSinker'
PIHOLE_DNS_: 208.67.222.222;208.67.220.220
DNSSEC: 'false'
VIRTUAL_HOST: pihole.cloud.local
PIHOLE_DOMAIN: pi.hole
volumes:
- "~/pihole/etc-pihole:/etc/pihole"
- "~/pihole/etc-dnsmasq.d:/etc/dnsmasq.d"
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.pihole.rule=Host(`pihole.cloud.local`)"
- "traefik.http.services.pihole.loadbalancer.server.port=80"
- "traefik.http.routers.pihole.tls=true"
- "traefik.http.routers.pihole.entrypoints=websecure"
networks:
traefik:
driver: bridge
name: traefik
ipam:
driver: default
config:
- subnet: 172.19.0.0/16
docker-compose up -d
VIRTUAL_HOST
to the /etc/hosts file on the Docker host to ensure it resolves:
sudo echo "10.2.3.4 pihole.cloud.local" >> /etc/hosts
http://pihole.cloud.local/admin
Option 3: Set Up Pihole and Traefik with SSL (TLS)¶
If you are not using Pi-hole over the internet and it's just for your local network, this option is unnecessary. Use this process if you need to host Pi-hole on a domain and want it secured with TLS. ** Note: Although many people still refer to it as SSL, the modern term is TLS. **
mkdir piholeSSL && cd piholeSSL && nano docker-compose.yaml
version: '3.8'
services:
traefik2:
image: traefik:latest
container_name: traefik
restart: always
command:
- "--log.level=DEBUG"
# Enable the Traefik Dashboard
- "--api.dashboard=true"
# Tell Traefik to discover containers using the docker API
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false" # Use false to only expose services explicitly
# Set up insecure listener to redirect all traffic to TLS
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
# Set up LetsEncrypt with ACME DNS-01 challenge via Cloudflare
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.letsencrypt.acme.email=${CLOUDFLARE_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
# Set up the TLS Configuration for websecure listener
- "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.domains[0].main=yourdomain.com"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.yourdomain.com"
environment:
CLOUDFLARE_EMAIL:username@email.com
CLOUDFLARE_DNS_API_TOKEN:<API-Token-String>
ports:
- "80:80" # The HTTP port
- "443:443" # The HTTPS port
networks:
- traefik
volumes:
- "/var/run/docker.sock:/var/run/docker.sock" # So Traefik can listen to Docker events
pihole:
image: pihole/pihole:latest
container_name: chacho-pihole
restart: always
ports:
- "5380:53/tcp"
- "5380:53/udp"
dns:
- 208.67.220.220
- 208.67.222.222
environment:
TZ: 'America/New York'
WEBPASSWORD: 'AdSinker'
PIHOLE_DNS_: 208.67.222.222;208.67.220.220
DNSSEC: 'false'
VIRTUAL_HOST: pihole.cloud.local
PIHOLE_DOMAIN: lan
volumes:
- "~/pihole/etc-pihole:/etc/pihole"
- "~/pihole/etc-dnsmasq.d:/etc/dnsmasq.d"
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.pihole.rule=Host(`pihole.cloud.local`)"
- "traefik.http.services.pihole.loadbalancer.server.port=80"
- "traefik.http.routers.pihole.tls=true"
- "traefik.http.routers.pihole.entrypoints=websecure"
networks:
traefik:
driver: bridge
name: traefik
ipam:
driver: default
config:
- subnet: 172.19.0.0/16