[Solved] Failed to allocate and map port 53-53 after system restart

Hello,

My Pi-hole container does not start automatically after a system (debian) restart :

$ sudo docker ps -a | grep pihole
ffb0952aee2a   pihole/pihole:latest                          "/s6-init"               4 minutes ago   Exited (128) About a minute ago                                                                                                                                                                                                                                                                                                                     pihole
$ sudo journalctl -u docker
...
time="2023-09-08T08:25:58.882268255+02:00" level=warning msg="Failed to allocate and map port 53-53: Error starting userland proxy: listen udp4 192.168.9.105:53: bind: cannot assign requested address"
time="2023-09-08T08:25:59.011007483+02:00" level=error msg="failed to start container" container=ffb0952aee2a6eaf77f99c0191b901da814acf1abf195b48c16cffdeeee33b71 error="driver failed programming external connectivity on endpoint pihole (9f1434b34c23047850468343890140a89012d63e38e1fbec0d1eac48752a1b3d): Error starting userland proxy: listen udp4 192.168.9.105:53: bind: cannot assign requested address"
...

If I manually restart using docker compose up -d, Pi-hole starts

$ sudo docker ps -a | grep pihole
ffb0952aee2a   pihole/pihole:latest                          "/s6-init"               8 minutes ago   Up 16 seconds (health: starting)   0.0.0.0:53->53/tcp, 192.168.9.105:53->53/udp, :::53->53/tcp, 67/udp, 0.0.0.0:50080->80/tcp, :::50080->80/tcp                                                                                                                                                                                                     pihole

Here is my docker-compose file :

version: "3"
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    networks:
      - home
    ports:
      - "53:53/tcp"
      - "192.168.9.105:53:53/udp"
      - "50080:80/tcp"
    environment:
      TZ: ${TZ}
      WEBPASSWORD: ${PIHOLE_WEBPASSWORD}
    volumes:
      - ${DATA_PATH}/pihole/etc-pihole/:/etc/pihole/
      - ${DATA_PATH}/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/
      - ${DATA_PATH}/pihole/var-log/pihole.log:/var/log/pihole.log
    dns:
      - 127.0.0.1
      - 1.1.1.1
    restart: always

networks:
  home:
    ipam:
      config:
        - subnet: 172.9.0.0/24

I did some tests/checks using a startup script (crontab reboot) :

  • port 53 is not used (nc -z -v -w 1 localhost 53)
  • delaying pihole container start does not fix the problem (sleep 120)

If I remove my host IP from the docker-compose ("192.168.9.105:53:53/udp" --> "53:53/udp"), the Pi-hole container starts well after a system restart but I have DNS resolution issues with my other containers.

Thanks a lot for your help!

PS : My problem is similar to that one but using the official Pi-hole image : Issues when restarting image jacklul/pihole


Debian version: 11.5
Docker version: 24.0.6
Docker Compose version: v2.21.0
Pi-hole version: Docker Tag 2023.05.2 / Pi-hole v5.17.1 / FTL v5.23 / Web Interface v5.20.1

Hi there.

I've had this problem before. It was very frustrating.

It is caused because you have this in your compose file.

I believe that it happens when the container starts after a bootup because the network interface (192.168.9.105) isn't quite ready.

what I did was to introduce a short delay into the containers starting up, and it solved it for me. I'll have to go through my notes to see how I did this.

cd /etc/systemd/system/

sudo mkdir docker.service.d

sudo touch override.conf

sudo nano override.conf


add these lines:

[Service]
# wait for the network to be up
ExecStartPre=/bin/sleep 10
4 Likes

Thank you very much for your help @Rhubarb, this service override did the trick !

I've made some improvements to the approach. Instead of sleeping for 10 seconds, I wrote a script to check for the connection to the router (IP server) every second, until it finds it. This way the start is quicker.

#!/bin/bash

ipServerAddress="192.168.0.1"
cycleLength=1 # The length of a wait cycle in seconds
timeout=15    # Maximum number of seconds to wait before giving up

elapsedTime=0
ping -c 1 $ipServerAddress > /dev/null 2>&1
while [ $? -ne 0 ]; do
    if [ "$elapsedTime" -ge "$timeout" ]; then
        # Timeout
        exit 1
    fi

    elapsedTime=$((elapsedTime + cycleLength))
    sleep $cycleLength
    ping -c 1 $ipServerAddress > /dev/null 2>&1
done

And then I call this script in the override.conf:

[Service]
# wait for the network to be up
ExecStartPre=/etc/systemd/system/docker.service.d/wait_for_network.sh

I've saved the script next to override.conf into /etc/systemd/system/docker.service.d/. If you save it somewhere else, make sure to call it with the appropriate path. And make sure that the script is executable (chmod +x wait_for_network.sh).

2 Likes

Hi,

Thanks, that’s a good suggestion. I think I may adopt that myself. I seem to remember that when I first encountered this issue I was in the middle of fixing a few other issues. Once I’d finished I never revisited this issue after the quick fix of waiting 10s. This is a much better idea.

Does

not work?

I did try that at the time, but it didn’t seem to work for me.. I don’t know why.. and as mentioned above I had a whole host of technical issues to work through at the time, so after a few hours of trying it, I just moved on to trying to delay the whole of docker.. a sledge hammer to crack a nut, I know, but it was a quick solution.

Now I have more time (fingers crossed) I should really go back and revisit the problem.

Just thinking about it after my reply above, I believe that it was docker that was trying to set up the network connection (because of the settings in the docker-compose file), and that attempt failed early on during start up. Hence delaying the start of pihole didn’t change that. The network error was raised by docker, not pihole.

I have the same issue. But I don't understand why it doesn't work by default?
/usr/lib/systemd/system/docker.service contains settings which dictate docker service to start only after the network is up!

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
Wants=containerd.service

Hey,

I was wondering the same thing as you - why doesn't systemctl wait for the network to be fully up before starting the Docker service? But I found a solution.

"Wants" is a weak form of "Requires" in systemd. It's so weak, in fact, that the Docker service can start even when the network isn't fully up!

To fix this, you can do the following:
sudo systemctl edit docker.service
Then add the following lines:

[Unit]
Requires=network-online.target docker.socket

After that, you don't need to restart systemd manually, since this issue only occurs after a reboot - and systemd is restarted automatically during that process.

This small edit fixed the issue for me, and now the Pi-hole container starts up like it should.