Docker – довольно эффективный метод запуска приложений в среде производства. Но что делать, если нужно запустить несколько приложений на одном хосте Docker? В такой ситуации можно настроить обратный прокси-сервер, который будет поддерживать открытыми только порты 80 и 443.
Traefik – это обратный прокси с поддержкой Docker, который предоставляет встроенную панель мониторинга. Данный мануал поможет настроить Traefik для маршрутизации запросов к двум разным контейнерам приложений:
Каждый контейнер подключен к БД MySQL. Traefik будет обслуживать все по HTTPS с помощью сертификата Let’s Encrypt.
Требования
- Сервер Ubuntu 16.04, настроенный с помощью этого руководства.
- Запущенный хост Docker.
- Docker Compose
- Домен и три записи А: db-admin, blog и monitor. Каждая запись должна указывать на IP-адрес хоста Docker. В руководстве используется условный домен example.com. Его нужно заменить вашим доменом.
1: Настройка и запуск Traefik
Проект Traefik предоставляет официальный образ Docker, который поможет быстро запустить Traefik в контейнере Docker.
Но прежде чем запустить контейнер Traefik, нужно создать конфигурационный файл и настроить зашифрованный пароль, чтобы получить доступ к панели мониторинга.
Используйте утилиту htpasswd, чтобы создать зашифрованный пароль. Установите утилиту, которая входит в пакет apache2-utils.
sudo apt-get install apache2-utils`
Затем сгенерируйте пароль с помощью htpasswd. Замените secure_password паролем, который вы хотите использовать для пользователя администратора Traefik:
htpasswd -nb admin secure_password
admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
Этот вывод используется в конфигурационном файле Traefic для настройки базовой аутентификации HTTP в панели мониторинга Traefik. Скопируйте всю строку, чтобы затем вставить ее в файл.
Чтобы настроить сервер Traefik,создайте файл traefik.toml в формате TOML. TOML – это стандартизированный язык конфигурации (аналогичный INI-файлам). Этот файл позволяет настроить сервер Traefik и дополнительные провайдеры. В этом мануале используются три доступных провайдера Traefik: web, docker и acme, который нужен для поддержки TLS сертификатов Let’s Encrypt.
nano traefik.toml
Добавьте две именованные точки входа, http и https, доступ к которым будет у всех бэкендов по умолчанию.
defaultEntryPoints = ["http", "https"]
Точки http и https будут настроены немного позже.
Настройте провайдер web, который дает доступ к интерфейсу панели мониторинга. Здесь нужно использовать строку, сгенерированную командой htpasswd:
...
[web]
address = ":8080"
[web.auth.basic]
users = ["admin:your_encrypted_password"]
Панель инструментов представляет собой отдельное веб-приложение, которое будет работать в контейнере Traefik по порту 8080.
Раздел web.auth.basic настраивает базовую аутентификацию HTTP для панели мониторинга. Вставьте вместо your_encrypted_password строку, сгенерированную утилитой htpasswd. Вы можете указать несколько пар учетных данных, разделив их запятыми.
Затем определите точки входа. Раздел entryPoints настраивает адрес, который будут слушать Traefik и контейнеры. Добавьте в файл строки:
...
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
Точка входа http обрабатывает порт 80, а точка входа https использует порт 443 для поддержки TLS/SSL. Весь трафик, поступающий по порту 80, будет автоматически перенаправлен в точку входа https, чтобы все запросы обслуживались только по защищенным соединениям.
Затем добавьте следующий раздел, чтобы настроить сертификат Let’s Encrypt для Traefik.
...
[acme]
email = "[email protected]"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false
Этот раздел называется acme, потому что ACME – это протокол, с помощью которого сервер взаимодействует с Let’s Encrypt для управления сертификатами. Чтобы Traefik создавал сертификаты для хостов, укажите в строке email свой адрес электронной почты. Затем нужно указать, что хранить информацию Let’s Encrypt нужно в файле JSON, acme.json. В строке entryPoint должен быть порт обработки точки входа 443 (в данном случае это точка входа https).
Последние ключи, onHostRule и onDemand, определяют, как Traefik будет создавать сертификаты. Сертификаты должны появиться сразу, как только будут созданы контейнеры с указанными именами хостов; за это отвечает настройка onHostRule. Параметр onDemand будет пытаться создать сертификаты при первом запросе. Это замедлит обработку запроса и пользователю придется ждать, потому лучше не использовать этот параметр.
Сохраните и закройте файл.
2: Запуск контейнера Traefik
Создайте сеть Docker для поддержки взаимодействия прокси-сервера и контейнеров. Сеть Docker необходима, так как ее можно использовать для работы с приложениями, запущенными в Docker Compose. Для примера можно назвать такую сеть proxy.
docker network create proxy
Когда контейнер Traefik будет запущен, нужно будет добавить его в эту сеть. Позже можно добавить в эту сеть дополнительные контейнеры, чтобы использовать Traefik в качестве прокси-сервера для этих контейнеров.
Затем создайте пустой файл, в котором будет храниться информация о шифровании Let’s Encrypt. Добавьте его в контейнер, чтобы Traefik мог его использовать.
touch acme.json
Затем заблокируйте разрешения этого файла, чтобы только пользователь root мог читать и изменять его. Если вы этого не сделаете, Traefik не удастся запустить.
chmod 600 acme.json
Создайте контейнер Traefik с помощью команды:
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD/traefik.toml:/traefik.toml \
-v $PWD/acme.json:/acme.json \
-p 80:80 \
-p 443:443 \
-l traefik.frontend.rule=Host:monitor.example.com \
-l traefik.port=8080 \
--network proxy \
--name traefik \
traefik:1.3.6-alpine --docker
Рассмотрим команду по частям:
- Флаг –d запускает контейнер в фоновом режиме как демон. Затем команда добавляет в контейнер файл docker.sock, благодаря чему процесс Traefik может прослушивать изменения в контейнерах. Также в контейнер можно поместить конфигурационный файл traefik.toml и acme.json.
- После этого порты 80 и 443 хоста Docker подключаются к одному и тому же порту в контейнере Traefik. Теперь Traefik получает все запросы HTTP и HTTPS.
- Затем нужно установить две метки Docker, которые будут направлять трафик на хост example.com по порту :8080 внутри контейнера Traefik, открывая панель мониторинга.
- В качестве сети контейнера нужно указать proxy. Контейнер называется traefik.
- Затем для создания контейнера используется образ traefik:1.3.6-alpine.
ENTRYPOINT образа Docker – это команда, которая запускается всегда, когда контейнер создается из образа. В этом случае команда представляет собой бинарный файл traefik внутри контейнера. Вы можете передать дополнительные аргументы этой команде при запуске контейнера. В этом случае можно передать аргумент -docker, который зарегистрирует провайдера docker с настройками по умолчанию. Провайдер docker позволяет Traefik выступать в качестве прокси-сервера контейнеров Docker. Конфигурация Docker по умолчанию отлично подходит, поэтому не нужно ее добавлять в traefik.toml.
После запуска контейнера у вас будет панель инструментов, с помощью которой можно просмотреть состояние контейнеров. Вы также можете использовать эту панель для визуализации интерфейсов и бэкэндов, которые зарегистрировал Traefik. Откройте панель мониторинга в браузере:
https://monitor.example.com
Будет предложено ввести имя пользователя и пароль администратора, и пароль (имя – admin, пароль – строка, которую вы сгенерировали в разделе 1).
После аутентификации на экране появится панель.
Пока что в панели еще не так много информации. Оставьте это окно открытым, и вы увидите, что содержимое панели изменится, когда вы добавите контейнеры для Traefik.
Теперь у вас есть прокси-сервер Traefik, настроенный для взаимодействия с Docker и готовый управлять другими контейнерами Docker.
3: Добавление контейнеров для Traefik
Контейнер Traefik запущен и готов обслуживать другие контейнеры приложений. Добавьте следующие контейнеры:
- Блог, запущенный с помощью официального образа WordPress.
- Сервер управления базами данных на основе официального образа Adminer.
Управлять обоими этими приложениями можно с помощью Docker Compose, используя файл docker-compose.yml:
nano docker-compose.yml
Укажите в файле версии и сеть:
version: "3"
networks:
proxy:
external: true
internal:
external: false
Версия 3 Docker Compose – это новейшая версия формата файла Compose.
Чтобы сервер Traefik мог опознать приложения, они должны входить в одну сеть. Поскольку используемая сеть создана вручную, нужно указать ее имя (proxy) и установить в external значение true. Затем нужно определить другую сеть, чтобы связать контейнеры с контейнером базы данных, который не будет обслуживаться контейнером Traefik. Эта внутренняя сеть будет называться internal.
Затем нужно определить все сервисы по очереди. Начать можно с контейнера blog, который основан на официальном образе WordPress. Добавьте в файл эту конфигурацию:
version: "3"
...
services:
blog:
image: wordpress:4.7.5-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.backend=blog
- traefik.frontend.rule=Host:blog.example.com
- traefik.docker.network=proxy
- traefik.port=80
networks:
- internal
- proxy
depends_on:
- mysql
Параметр environment позволяет указать переменные среды, которые будут установлены внутри контейнера. Если значение WORDPRESS_DB_PASSWORD не установлено, Docker Compose будет извлекать его из оболочки и передавать при создании контейнера. Определить эту переменную среды можно в оболочке перед запуском контейнеров. Таким образом, пароли не попадут в конфигурационный файл.
В разделе labels указываются параметры Traefik. Метки Docker сами по себе ничего не делают, но Traefik читает их и понимает, как обращаться с контейнерами. Каждая метка выполняет такие действия:
- traefik.backend определяет имя сервиса бэкенда (который указывает на контейнер blog).
- traefik.frontend.rule=Host:blog.example.com исследует запрашиваемый хост и, если он совпадает с шаблоном blog.example.com, перенаправляет трафик в контейнер blog.
- traefik.docker.network=proxy определяет сеть, в которой Traefik может найти внутренний IP-адрес контейнера. Поскольку Traefik имеет доступ ко всей информации Docker, он может случайно выбрать IP сети internal, если сеть не указана явно.
- traefik.port указывает порт, который Traefik должен использовать для маршрутизации трафика в контейнеры.
При такой конфигурации весь трафик, отправленный на порт 80 хоста Docker, будет перенаправлен в контейнер blog.
Этот контейнер принадлежит двум различным сетям, чтобы Traefik мог найти его через сеть proxy и связываться с контейнером базы данных через сеть internal.
Параметр depends_on помогает Docker Compose понять, что этот контейнер нужно запускать после запуска его зависимостей. Поскольку для работы WordPress необходима запущенная БД, контейнер mysql запускается раньше, чем контейнер blog.
Теперь настройте сервис MySQL:
services:
...
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
Для создания этого контейнера используется официальный образ MySQL 5.7. Обратите внимание: параметр environment снова не имеет значения. Для переменных MYSQL_ROOT_PASSWORD и WORDPRESS_DB_PASSWORD необходимо установить одинаковое значение, чтобы контейнер WordPress мог связываться с MySQL. Контейнер mysql не должен взаимодействовать с Traefik или с внешним миром, потому он принадлежит только сети internal. Поскольку Traefik имеет доступ к сокету Docker, процесс по-прежнему будет открывать фронтенд контейнера mysql по умолчанию. Поэтому нужно добавить метку traefik.enable = false, чтобы Traefik не смог сделать этот контейнер доступным.
Теперь нужно добавить параметры контейнера Adminer:
services:
...
adminer:
image: adminer:4.3.1-standalone
labels:
- traefik.backend=adminer
- traefik.frontend.rule=Host:db-admin.example.com
- traefik.docker.network=proxy
- traefik.port=8080
networks:
- internal
- proxy
depends_on:
- mysql
Этот контейнер основан на официальном образе Adminer. Параметры network и depends_on совпадают с этими же параметрами контейнера blog.
Однако поскольку весь трафик порта 80 хоста Docker направляется непосредственно в контейнер blog, нужно настроить контейнер adminer немного иначе, чтобы он получал свой трафик. Благодаря строке traefik.frontend.rule=Host:db-admin.example.com сервер Traefik будет проверять запрашиваемый хост. Если он соответствует шаблону db-admin.example.com, Traefik направит трафик в контейнер adminer.
Сохраните и закройте файл.
Теперь нужно задать значения переменных WORDPRESS_DB_PASSWORD и MYSQL_ROOT_PASSWORD, прежде чем запустить контейнеры.
export WORDPRESS_DB_PASSWORD=secure_database_password
export MYSQL_ROOT_PASSWORD=secure_database_password
Вместо secure_database_password укажите надежный пароль БД.
Теперь запустите контейнеры:
docker-compose up -d
Снова откройте панель Traefik. Вы увидите, что в ней появились новые контейнеры, а также backend и frontend.
Откройте в браузере blog.example.com (где example.com – ваш домен). Соединение будет перенаправлено на зашифрованный порт 443. Теперь можно закончить установку WordPress.
После этого откройте в браузере db-admin.example.com. Контейнер mysql не доступен в интернете, но контейнер adminer имеет доступ к нему через внутреннюю сеть Docker (internal).
На экране появится форма входа Adminer. Используйте имя пользователя root, укажите mysql в качестве server, в поле пароля введите значение переменной MYSQL_ROOT_PASSWORD. После этого вы получите доступ к интерфейсу Adminer.
Оба сайта теперь работают. Чтобы получить доступ к панели мониторинга, введите monitor.example.com.
Заключение
Теперь сервер Traefik проксирует запросы в контейнеры приложений Docker.
Traefik позволяет легко настраивать большое количество сервисов и устраняет необходимость перезапускать контейнер traefik при добавлении новых приложений в контейнер traefik. Traefik незамедлительно получает все сведения об изменениях через файл сокета Docker.