Ответ 1
Проблема в том, что многие современные Linux-системы неявно запускают dnsmasq, поэтому теперь вы хотите настроить второй экземпляр специально для Docker. Для этого необходимо 3 настройки:
-
--interface=docker0
для прослушивания сетевого интерфейса Docker по умолчанию -
--except-interface=lo
, чтобы пропустить неявное добавление интерфейса loopback -
--bind-interfaces
, чтобы отключить функцию dnsmasq, где она по-прежнему прослушивает все интерфейсы по умолчанию, даже когда ее единственный обрабатывающий трафик для одного из них
Настройка выделенного экземпляра dnsmasq
Вместо того, чтобы изменять настройки экземпляра dnsmasq по умолчанию для всей системы, эти инструкции показывают настройку выделенного экземпляра dnsmasq с systemd в системе, которая уже определяет службу dnsmasq по умолчанию:
$ sudo cp /usr/lib/systemd/system/dnsmasq.service /etc/systemd/system/dnsmasq-docker.service
$ sudoedit /etc/systemd/system/dnsmasq-docker.service
Сначала мы копируем настройки службы по умолчанию в выделенный файл службы. Затем мы редактируем этот служебный файл и ищем раздел определения сервиса, который должен быть примерно таким:
[Service]
ExecStart=/usr/sbin/dnsmasq -k
Мы редактируем этот раздел для определения наших дополнительных параметров:
[Service]
ExecStart=/usr/sbin/dnsmasq -k --interface=docker0 --except-interface=lo --bind-interfaces
весь файл на самом деле довольно короткий:
[Unit]
Description=DNS caching server.
After=network.target
After=docker.service
Wants=docker.service
[Service]
ExecStart=/usr/sbin/dnsmasq -k --interface=docker0 --except-interface=lo --bind-interfaces
[Install]
WantedBy=multi-user.target
В разделе [Unit]
система systemd ожидает, что после того, как сетевой стек и главный демон docker будут доступны для запуска этой службы, в то время как [Install]
указывает, какое целевое состояние системы должно добавить службу при включении.
Затем мы настраиваем нашу новую службу для запуска при загрузке системы, а также запускаем ее явно для немедленного использования:
$ sudo systemctl enable dnsmasq-docker
$ sudo systemctl start dnsmasq-docker
Как последний шаг при запуске службы, мы проверяем, что она действительно началась, как ожидалось:
$ sudo systemctl status dnsmasq-docker
Две ключевые строки, которые мы ищем в этом выпуске:
Loaded: loaded (/etc/systemd/system/dnsmasq-docker.service; enabled; vendor preset: disabled)
Active: active (running) since <date & time>
В первой строке обратите внимание на статус "включено", а во втором - статус "активный (рабочий)". Если служба не запущена правильно, то дополнительная диагностическая информация, мы надеемся, объяснит, почему (хотя она может быть, к сожалению, загадочной время от времени, следовательно, этот пост).
Примечание. Эта конфигурация может не запускать dnsmasq-docker
при перезапуске системы с ошибкой об интерфейсе docker0
, который не определен. Ожидание docker.service
кажется довольно надежным в предотвращении этой проблемы, если разрешение имен из контейнеров докеров не работает после перезагрузки системы, попробуйте запустить:
$ sudo systemctl start dnsmasq-docker
Настройка брандмауэра хоста
Чтобы иметь возможность использовать преобразователь из локальных контейнеров Docker, нам также необходимо удалить сетевой брандмауэр между хостом и системами, запущенными в контейнерах:
sudo firewall-cmd --permanent --zone=trusted --change-interface=docker0
sudo firewall-cmd --reload
(Это было бы абсолютно ужасной идеей на хосте производственного контейнера, но может быть полезным компромиссом с учетом риска и преимущества на рабочей станции разработчика)
Настройка Docker с использованием файла systemd environment
Теперь, когда у нас работает наш локальный преобразователь, нам нужно настроить Docker для его использования по умолчанию. Докеру нужен IP-адрес интерфейса docker0
, а не имя интерфейса, поэтому мы используем ifconfig
для получения этого:
$ ifconfig docker0 | grep inet
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
Итак, для моей системы интерфейс хоста на мосте по умолчанию docker0
доступен как 172.17.0.1
(добавление | cut -f 10 -d ' '
к этой команде должен отфильтровывать вывод только с IP-адресом)
Так как я предполагаю Linux на базе systemd с системным пакетом Docker, мы запросим файл служебного пакета системы, чтобы узнать, как запускается служба:
$ cat /usr/lib/systemd/system/docker.service
Первое, что мы ищем, это точная команда, используемая для запуска демона, которая должна выглядеть примерно так:
ExecStart=/usr/bin/docker daemon \
$OPTIONS \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$INSECURE_REGISTRY
Вторая часть, которую мы ищем, заключается в том, настроена ли служба для использования файла среды, как указано одной из следующих строк:
EnvironmentFile=-/etc/sysconfig/docker
Когда файл окружения используется (как в Fedora 23), тогда изменить параметры Docker-демона - это отредактировать этот файл и обновить соответствующую переменную среды:
$ sudoedit /etc/sysconfig/docker
Существующая запись OPTIONS
в Fedora 23 выглядит так:
OPTIONS='--selinux-enabled --log-driver=journald'
Чтобы изменить настройки разрешения DNS по умолчанию, изменим его так:
OPTIONS='--selinux-enabled --log-driver=journald --dns=172.17.0.1'
И затем перезапустите демон Docker:
$ sudo systemctl restart docker
С учетом этих изменений контейнеры Docker теперь должны быть надежно доступны для доступа к любым системам, к которым может обращаться ваша хост-система (в том числе через VPN-туннели, что было моей собственной причиной, чтобы понять это)
Вы можете запустить curl
внутри контейнера, чтобы проверить правильность разрешения имен:
docker run -it centos curl google.com
Замените google.com
на то, какое имя хоста выдавало вам проблемы (так как вы должны были только найти этот ответ, если у вас была проблема с разрешением имен при запуске процесса внутри контейнера Docker)
Настройка Docker с помощью выпадающего файла systemd
(Предостережение: поскольку моя система использует файл окружения, я не смог протестировать приведенный ниже подход к основанию на основе файлов, но он должен работать - я включил его, поскольку документация Docker, похоже, указывает на то, что они теперь предпочитают использовать файлы drop-in systemd для использования файлов среды)
Если системный служебный файл не использует EnvironmentFile
, то вся запись ExecStart
может быть заменена с помощью файла конфигурации сбрасывания:
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudoedit /etc/systemd/system/docker.service.d/daemon.conf
Затем мы советуем Docker очистить существующую запись ExecStart и заменить ее на новую с дополнительными настройками:
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon \
$OPTIONS \
--dns 172.17.0.1 \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$INSECURE_REGISTRY
Затем мы сообщим systemd загрузить это изменение конфигурации и перезапустить Docker:
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
Литература:
- Ссылка на docker systemd: https://docs.docker.com/engine/admin/systemd/
- ссылка на файл systemd: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
- Ссылка dnsmasq: http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
- ссылка на firewalld: https://fedoraproject.org/wiki/FirewallD
- Настройка dnsmasq без существующего локального резольвера на хосте: http://docs.blowb.org/setup-host/dnsmasq.html