Hi, is it possible to make 2 Piholes running in a container with macvlan network on 2 different Raspberry PI5s high available (HA) with Keepalived?

I know it maybe sufficient to configure the 2 different Pihole IP addresses in the clients, but I was wondering is it possible to make these 2 Piholes high available via 1 virtual IP address.

The 2 Piholes are running ok in their containers.

  • pihole01 ip address: 192.168.0.251
  • pihole02 ip address: 192.168.0.252
  • Intended virtual ip address: 192.168.0.250

The pihole container can be reached from the host they are running on. Without additional routing on the host this is not possible.

pihole02 is sync’ed with pihole01 using Nebula (containerized).

The Piholes are working fine. The cherry on the pudding would be to have this setup high available via Keepalived. Is this possible?

Due to the macvlan the pihole’s have their own IPs. As such running Keepalived on the host does not make sense (to my opinion) as that would not check the Pihole availability but the host availability. And as well, if the virtual IP would be assigned to the host, all other services (containers) would get that same virtual IP as well, while perhaps only the Pihole is down and non of the other containers.

Or is that a wrong assumption and is it possible to monitor the pihole containers with keepalived on host where the containers are running and somehow assign the virtual IP to one of the piholes?

I experimented a bit, by installing keepalived in a pihole container. Created a /etc/keepalived/keepalived.conf config file. And launched keepalived as follows: keepalived -n -l -D. That seems to do something:

Sun Sep 21 17:41:47 2025: (VI_1) removing VIPs.
Sun Sep 21 17:41:47 2025: Startup complete
Sun Sep 21 17:41:47 2025: Netlink: error: Operation not permitted(1), type=RTM_DELADDR(21), seq=1758469311, pid=0
Sun Sep 21 17:41:47 2025: (VI_1) Entering BACKUP STATE (init)

But I don't see the virtual IP 192.168.0.250 in the ip a output. Is keepalived not allowed to change the network configuration of the container?

If the above would be working, would it be possible to equipment the Pihole container with keepalived?

If the above will not work, would it be possible to use a keepalived container, and have keepalived 'monitor' the 2 piholes from remote and have the virtual IP address assigned to one of the 2 piholes?

Looking forward to what is possible with keepalived to make keepalived running in containers with macvlan high available.

Reference topic.

Thanks in advance

Small update:

I updated my pihole compose file and added:

    environment:

      ADDITIONAL_PACKAGES: 'keepalived'

And enabled:

    cap_add:
      # See https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
      # Required if you are using Pi-hole as your DHCP server, else not needed
      - NET_ADMIN

Created the config file again and the keepalived command, used earlier. The output is now:

Sun Sep 21 19:19:49 2025: Registering Kernel netlink command channel
Sun Sep 21 19:19:49 2025: Assigned address 192.168.0.251 for interface eth0
Sun Sep 21 19:19:49 2025: Registering gratuitous ARP shared channel
Sun Sep 21 19:19:49 2025: (VI_1) removing VIPs.
Sun Sep 21 19:19:49 2025: Startup complete
Sun Sep 21 19:19:49 2025: (VI_1) Entering BACKUP STATE (init)

And the virtual IP is shown in the output of ip a.

Is there a way to automatically start the keepalived command after the container is started???

Your question isn't related to DNS in general nor Pi-hole in particular.

It is about networking, specifically how you could bring up Docker containers in order, and whether it would be a good idea to use a virtualised keepalived to monitor interface availability.

You should consider to consult forums specialising in keepalived and Docker networking.

@Bucking_Horn I just wanted to come back here, to write that I've it more or less working: 2 piholes running in docker containers with their own IPs (because of macvlan).

More or less because it actually works, but the only thing that is missing is the possibility to launch the keepalived command when the container is started. I think that this makes my question specific to this pihole/docker forum.

The big question I've now: is it possible to launch the command keepalived --use-file=/etc/pihole/keepalived/keepalived.conf --config-id pihole01 during the bringup of the pihole container?

As can been seen in the command, the keepalived.conf has been made part of the /etc/pihole configuration. This way the keepalived config is persistent.

Not visible, the keepalived.conf was made for both piholes pihole01 and pihole02. During the launch of the command either one is specifeid.

To summarize: two questions related to this the pihole high availability setup a reality:

  • Is it possible to configure a pihole configid (e.g. pihole01 or 02) in the pihole docker compose file?
  • Is it possible to launch an additional command during the container bringup?

This approach seems flawed:
If you tie keepalived to a running Pi-hole container instance, it would fail to operate correctly if your system would fail to start Docker or to start the Pi-hole container, and possibly also if Pi-hole itself would not be operational while the container starts up ok.

Instead, keepalived should monitor whether your Pi-hole is indeed both running as well as operational - i.e. keepalived should be external to Pi-hole, capable of operating independently, and maybe even of starting Docker as well as required containers.

This would be your generic problem:
How to best operate keepalived on a pair of Docker containers?

EDIT:

This is a generic Docker question about naming a container.

This is a generic Docker question about using lifecycle hooks with a Docker container on a specific deployment platform, e.g. Use lifecycle hooks | Docker Docs.

It will work as intended :grinning_face:

keepalived assigns a virtual IP (VIP) to the pihole instance that is available. More than 2 piholes can be involved, btw. It is not a monitor to keep a pihole running!

In the keepalived I just configured I monitor the pihole process as well.

So, if the host fails, or the container is started but the pihole process is not, or the pihole process stops or think of any other anomalies the VIP points to the other available pihole.
This way the DNS service remains available via the virtual IP :grinning_face:

Exactly as intended.

The only thing missing is the configuration to launch it from within the container during container startup.

You will need to create your own docker image, using Pi-hole image as base and adding the scripts and commands you want to execute.

Nice idea. Let's if that is possible:

I tried to build the docker image, but it fails.
Is there a description how to build the Image?

Cloned the docker-pihole repository.

$ docker build -t test-image .
[+] Building 1.7s (16/19)                                                                                                                                   docker:default
 => [internal] load build definition from Dockerfile                                                                                                                  0.0s
 => => transferring dockerfile: 5.69kB
....
 => ERROR [base  8/10] RUN cd /etc/.pihole && .....

0.147 install: cannot stat './advanced/bash-completion/pihole': No such file or directory

Is there a description how to build the image using the docker-pihole/src/Dockerfile?

This is another Docker question:
You don't need to clone a repository to base your image on an existing container.

But once you start modifying Docker images, that's usually a strong indication that you are on the wrong track.
Docker is about using containers configured from existing images, not maintaining your own creations.

I repeat once more that your issue is completely independent of Pi-hole:
It doesn't matter what machine you want keepalived to provide IP address failover for - it will always be the same pattern.

Forcing keepalived's configuration into your Pi-hole container would be a severe design flaw in your solution.
That configuration is specific for keepalived, not for Pi-hole.

You should look into solving your real question:

Or in the way you've put it: "How to make XXX in container with macvlan, high available with Keepalived?"

A precursory search brings up a few hits how others have done that with Docker containers with using macvlan network mode, adopting nothing else but keepalived's docker-compose and keepalived's configuration.

The interesting bit appears to be how they succeeded in coupling keepalived to the macvlan IPs of their master and backup containers IPs:
Simply by referring their keepalived container's network mode to that of their container's service (e.g. like network_mode: service:pihole if those would be created using Pi-hole's Docker sample configuration).

@Bucking_Horn Thanks a lot for your persistent support.

Using the keepalived image in combination with the network-mode made Pihole high-available in the Docker way, at least as far as I can determine at the moment.

DNS (Pihole) is such an essential network functionality that it must be available all the time, more then other network services. Hence I want Pihole to be High Available, that's why I believe that my question belong here in the Pihole+Docker forum (at least more then with other services).

Once more thanks a lot for your awesome pointer, learned something new again, today :grinning_face: