Дозвіл імен доменів з контейнерів Docker у складних випадках

В питанні, пов'язаному з DNS попив мені Docker кровиночки ґрунтовно, бо там стільки різних місць в яких тобі пропонують написати заповітні цифри, що прямо-таки очі розбігаються.

Отже, завдання: необхідно підняти оточення розробника для одночасної роботи з декількома веб-проектами висячими на доменах виду example.app. При цьому дані домени повинні бути доступні з контейнерів, з хоста, а також, наприклад, з емулятора Genymotion. Крім того, з контейнерів повинен бути доступний і зовнішній інтернет. Все це посилюється корпоративних Intranet зі своїм внутрішнім DNS сервером.

Для рішення нам буде потрібно:

  1. docker — движок для роботи з контейнерами
  2. docker-compose — робота з мульти-контейнерними рішеннями
  3. dnsmasq — легкий DNS (а також DHCP і TFTP)
  4. laradock (опціонально) — готове мульти-контейнерне рішення для розробника
Установку пп.1-3 пропускаю, як очевидну. Зверніть увагу на версію docker-compose, нам потрібна версія 1.8 або вище (на момент написання в архівів лежала стара версія).

Для досвідченого працівника дока докера немає ніякої проблеми вибрати потрібні образи, слинковать їх, прокинути порти, встановити додаткові бібліотеки — інформації на цю тему достатньо. Але якщо ви хочете почати роботу прямо зараз, то давайте скористаємося продуктом колективного свідомого — laradock.

З назви laradock можна виявити натяк на змичку Laravel + Docker. Так і було спочатку, але в даний момент така спрямованість пішла і тепер проект орієнтується на будь-які веб-додатки.
Отже, laradock — це yml-файл і набір супутніх сконфігурованих образів для
docker-compose
, що дозволяє розгортати набір контейнерів з nginx, mysql, mongoDB і ще купою різних штучок типу Memcached, Aerospike і т. д. (вже зараз набір дуже широкий і постійно розширюється).
Важливим є те, що встановлення деяких додаткових плагінів або бібліотек зводиться до простої правці yml-файлу, наприклад:

- INSTALL_XDEBUG=true

і пересборке образу:

docker-compose build php-fpm

Крім того, в laradock все готово, щоб засунути туди одночасно стільки проектів, скільки душі завгодно — просто зверніть увагу на приклади конфігурації
./nginx/sites
.

laradock прокидає порт 80 з контейнера nginx/apache на хост-машину, тому щоб після підняття потрібних контейнерів (набір ви обираєте самостійно)

docker-compose up -d nginx mysql phpmyadmin

побачити сконфігуровані заздалегідь в nginx/apache сайти example.app і mysite.app потрібно просто прописати для них локальний IP у файлі /etc/hosts

127.0.0.1 example.app
127.0.0.1 mysite.app

Контейнер phpmyadmin прокидывется на порт 8080, тому побачити його в роботі можна за адресою
http://localhost:8080
. Ну і майте на увазі, що контейнер з мускулом працює для всіх інших контейнерів на хості
mysql
, до якого і слід підключатися.
насправді, якщо у вас ізольовані проекти і немає корпоративної intranet, то ви можете зупинитися в даному місці і вже почати розробку. Проблема з DNS вас не торкнулася.

Якщо ви читаєте далі, то вам мабуть потрібно:

  1. З свого додатку звернутися до свого ж окремому backend на іншому домені.
  2. З програми, запущеного в емуляторі Android (iOS і т. д.) звернутися до свого backend.
  3. З свого додатку звернутися до стороннього API, але ви сидите в intranet з місцевим DNS-сервером.
Отже, вирішуємо пункти 1 і 2. Пункт 3 вирішиться сам собою, доданням всього однієї рядка — адреси вашого intranet DNS. Зробимо так, щоб наші домени були доступні з контейнерів (зокрема з php-fpm). Для цього нам знадобиться dnsmasq.

Встановлюємо його, якщо ви ще цього не зробили:

sudo apt-get install dnsmasq

Для того, щоб дозволити DNS ім'я dnsmasq заглядає в /etc/resolv.conf в пошуках IP вищого DNS-сервера. В принципі, ми могли б туди його і прописати, але в цьому файлі чітко написано, що змінювати його не варто, оскільки він може бути перезаписаний. Тому створимо власний файл /etc/resolv.ext.conf з наступним вмістом:

# Гуглівського DNS
nameserver 8.8.8.8
nameserver 8.8.4.4

# Корпоративний DNS (це і є та сама терміну, яка виведе вас із катівень інтранет)
nameserver <IP корпоративного DNS>

Тепер потрібно щоб dnsmasq став його використовувати. У файлі /etc/dnsmasq.conf потрібно знайти, розкоментувати і виправити параметр, вказавши там наш файл:

resolv-file=/etc/resolv.ext.conf

Однак не все так просто… хитрий dnsmasq не буде його використовувати, поки ми не виконаємо ще одну маніпуляцію.

Тут потрібно зробити маленьку ремарку: можна не морочитися з власним файлом конфігурації, а засунути nameserver'а в оригінальний resolv.conf, але засунути правильно. Засовувати їх потрібно в /etc/resolvconf/resolv.conf.d/head і тоді вони будуть автоматично додаватися до початку resolv.conf Однак майте на увазі, що там може бути тільки 3 неймсервера, а у своєму файлі — скільки завгодно.
Але повернемося до нашого випадку. Для того, щоб наш resolv.ext.conf всеж був прочитаний необхідно у файлі /etc/default/dnsmasq вказати:

IGNORE_RESOLVCONF=yes

Що за маячня, скажете ви… Ігнорувати файл, щоб його прочитати? Не зовсім так. Коментар перед цією опцією чітко роз'яснює що вона робить. Ми змушуємо dnsmasq ігнорувати висновок утиліти
resolvconf
, якщо вона встановлена і звернути увагу саме на наш файл.
В цілому це все. Залишилося тільки пояснити Docker, що в нашому маленькому світі за дозвіл DNS відповідає dnsmasq. Відкриваємо /etc/default/docker і вказуємо:

DOCKER_OPTS="--dns 127.0.0.1"

Рестартуем сервіси:

sudo service dnsmasq restart
sudo service docker restart

...

… знову заминка:

все запрацює тільки якщо у вашому лінуксі використовується система ініціалізації Upstart або SysVinit (про це чітко написано в даному файлі). Але якщо ви використовуєте, наприклад, Ubuntu 15.04 або вище, то у вас використовується вже більш просунута systemd і нам будуть потрібні додаткові рухи. Але для початку перевіримо, що ж ми використовуємо:

$ sudo stat /proc/1/exe
Файл: '/proc/1/exe' -> '/lib/systemd/systemd'

Як бачите, з виводу команди стає ясно що саме використовується у нас. В даному випадку systemd.

Ну що ж, вилікуємо і цього. Конфігурація сервісу спочатку лежить в /lib/systemd/system/docker.service. Можна його просто скопіювати і підправити:

sudo cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service

але ми зробимо більш порядно — змінимо тільки те, що слід змінити:

sudo [ ! -e /etc/systemd/system/docker.service.d/ ] && mkdir -p /etc/systemd/system/docker.service.d/
sudo cat << 'EOF' > /etc/systemd/system/docker.service.d/docker.conf
[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS

EOF

Як ви вже зрозуміли, ми створили файл /etc/systemd/system/docker.service.d/docker.conf (так званий drop-in) зі змінами стандартних параметрів і передаємо наші параметри dns, прописані в
/etc/default/docker
при старті сервісу.

Залишилося тільки перезапустити сервіси:

sudo systemctl daemon-reload
sudo service docker restart

і переконатися, що все в порядку:

sudo service docker status

У висновку цієї команди ви побачите багато вже знайомого: і підключений drop-in, й стартував сервіс з нашим dns. Ось тепер дійсно !

Корисні посилання:

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.