Docker: имена не разрешаются внутри контейнера
Внутри контейнера разрешение имён идёт через встроенный сервер Docker, который пересылает запросы серверам хоста. Ломается это обычно из-за локального разрешателя на 127.0.0.53: адрес петлевого интерфейса внутри контейнера означает сам контейнер.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
В resolv.conf хоста указан петлевой адрес
Docker не может передать контейнеру адрес 127.0.0.53: внутри он указывает на сам контейнер. Тогда Docker подставляет публичные серверы, и внутренние имена перестают разрешаться.
-
Сеть контейнера без встроенного разрешателя
В сети по умолчанию разрешение имён между контейнерами не работает: для этого нужна своя сеть.
-
Брандмауэр блокирует запросы контейнеров
Правила на хосте могут не пропускать запросы из подсети контейнеров.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Какие серверы имён видит контейнер.
docker run --rm alpine cat /etc/resolv.confЧто настроено на хосте.
cat /etc/resolv.confРаботает ли разрешение имён изнутри.
docker run --rm alpine nslookup example.org 2>&1 | headРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Docker не может передать контейнеру адрес 127.0.0.53: внутри он указывает на сам контейнер. Тогда Docker подставляет публичные серверы, и внутренние имена перестают разрешаться.
- Как проверить
-
Посмотрите resolv.conf хоста и контейнера.
cat /etc/resolv.conf docker run --rm alpine cat /etc/resolv.conf 2>/dev/null
- Как исправить
-
Задайте серверы имён явно в daemon.json: тогда Docker будет передавать их контейнерам.
# /etc/docker/daemon.json # {"dns": ["10.0.0.1", "1.1.1.1"]} sudo systemctl restart docker
- Почему происходит
- В сети по умолчанию разрешение имён между контейнерами не работает: для этого нужна своя сеть.
- Как проверить
-
Посмотрите сети и подключение контейнера.
docker network ls docker inspect имя_контейнера --format "{{json .NetworkSettings.Networks}}" 2>/dev/null | head -c 300
- Как исправить
- Создайте отдельную сеть и подключите контейнеры к ней: внутри неё имена контейнеров разрешаются автоматически.
- Почему происходит
- Правила на хосте могут не пропускать запросы из подсети контейнеров.
- Как проверить
-
Проверьте разрешение изнутри и правила.
docker run --rm alpine nslookup example.org 2>&1 | head sudo nft list ruleset 2>/dev/null | grep -i docker | head
- Как исправить
- Разрешите запросы имён из подсети контейнеров.
Пример вывода
Контейнер получил публичные серверы вместо внутренних. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
$ cat /etc/resolv.conf
nameserver 127.0.0.53
$ docker run --rm alpine cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
app[1]: error: lookup db.internal: no such host
Связанные ошибки
- Temporary failure in name resolution в журнале службы Служба не может разрешить имя: не готова сеть, нет сервера имён, мешает изоляция. Разбор при загрузке и в работе.
- systemd-resolved: resolv.conf заменён обычным файлом Разрешение имён работает частично: поиск по домену и разные серверы по интерфейсам перестают действовать.
- Docker: unable to configure the Docker daemon with file daemon.json Демон Docker не запускается из-за ошибки в /etc/docker/daemon.json: неверный JSON или неизвестный ключ.
- Docker: правила брандмауэра конфликтуют с вашими После перезапуска брандмауэра контейнеры теряют сеть: Docker управляет своими правилами сам.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Automount: каталог монтируется не вовремя или отваливается Автомонтирование через .automount: как работает TimeoutIdleSec, почему ресурс отваливается и когда лучше обычный .mount.
- BIND: порт 53 занят systemd-resolved named не может занять порт 53: его держит локальный разрешатель имён. Как развести их по адресам.
- Broken pipe в журнале службы Запись в закрытый канал или соединение: клиент отключился, обработчик завершился, конвейер разорван.
Где встречается чаще всего
Источники
- Документация Docker: настройка DNS контейнеров
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Проверено на Ubuntu 24.04 с systemd-resolved: контейнер получает публичные серверы.