“No route to host” in Docker

Ieri ho avuto la necessità di creare al volo un’istanza di MariaDB per un progetto Python, e naturalmente avevo anche la necessità di un tool per poter gestire comodamente il database: phpmyadmin.

La scelta è ricaduta sull’uso di Docker, e quindi ho creato il seguente file di composizione:

version: '3.2'

services:
  db:
    image: mariadb:latest
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=secret
    volumes:
      - ./data:/var/lib/mysql
  phpmyadmin:
    image: phpmyadmin
    restart: always
    ports:
      - 8080:80
    environment:
      - PMA_HOST=db
    depends_on:
      - db

Avvio la mia istanza con un semplice

docker-compose up -d

E in pochi secondi accedo tranquillamente in localhost alla porta 8080 su phpmyadmin.

Inserisco le credenziali root / secret e mi compare il messaggio di errore: mysqli::real_connect(): (HY000/2002): No route to host.

Errore in phpmyadmin che non riesce a collegarsi al container del database, restituendo l’errore no route to host.

Vi risparmio i tentativi inutili, ma il firewall di Linux/Ubuntu (firewalld) in pratica vedeva i network di Docker come reti pubbliche, e quindi sostanzialmente dove il livello di sicurezza è basso.

Ecco infatti la situazione del mio firewall prima di lanciare Docker.

Configurazione di firewalld prima di lanciare Docker

Una volta lanciato Docker, ecco che compaiono delle nuove connessioni a sinistra, una si chiama docker0 e le altre hanno un nome del tipo br-*.

Docker crea nuove connessioni nel firewall

Se impostiamo queste connessioni su trusted tutto riprende a funzionare normalmente… fino al prossimo reboot.

Trusted significa che è una connessione di cui ci fidiamo.

Ecco ora che possiamo collegarci normalmente al nostro database.

Se vogliamo però che il problema si risolva per sempre, è necessario impostare questa modifica in modo permanente. Per farlo, basta salvare il runtime su disco, cliccando su Opzioni –> Runtime su permanente.

Per fare le stesse cose da terminale (ovviamente usando un utente con permessi amministrativi):

firewall-cmd --zone=trusted --add-interface=docker0 --permanent
firewall-cmd --zone=trusted --add-interface=br-a07e3e901d53 --permanent
firewall-cmd --zone=trusted --add-interface=br-8a47ba664107 --permanent
firewall-cmd --reload