Поиск по сайту:

Как использовать Traefik в качестве обратного прокси-сервера для контейнеров Docker в Ubuntu 18.04


Автор выбрал программу Write for DOnations.

Примечание. Это руководство предназначено для Traefik v1. Если вы хотите установить и настроить Traefik v2, воспользуйтесь этим новым руководством.

Введение

Docker может быть эффективным способом запуска веб-приложений в рабочей среде, но вам может понадобиться запустить несколько приложений на одном хосте Docker. В этой ситуации вам нужно настроить обратный прокси-сервер, так как вы хотите открыть только порты 80 и 443 для остального мира.

Давайте зашифруем.

Предпосылки

Чтобы следовать этому руководству, вам понадобится следующее:

  • руководство по первоначальной настройке сервера Ubuntu 18.04. Это включает пользователя sudo без полномочий root и брандмауэр.
  • Docker установлен на вашем сервере, что вы можете сделать, следуя инструкциям по установке и использованию Docker в Ubuntu 18.04.
  • Docker Compose установлен в соответствии с инструкциями из раздела Как установить Docker Compose в Ubuntu 18.04.
  • Домен и три записи A, db-admin, blog и monitor, каждая из которых указывает на IP-адрес вашего сервера. Вы можете узнать, как указать домены на дроплеты DigitalOcean, прочитав документацию DigitalOcean по доменам и DNS. В этом руководстве замените ваш_домен своим доменом в файлах конфигурации и примерах.

Шаг 1 — Настройка и запуск Traefik

У проекта Traefik есть официальный образ Docker, поэтому мы будем использовать его для запуска Traefik в контейнере Docker.

Но прежде чем мы запустим и запустим наш контейнер Traefik, нам нужно создать файл конфигурации и установить зашифрованный пароль, чтобы мы могли получить доступ к панели мониторинга.

Мы будем использовать утилиту htpasswd для создания этого зашифрованного пароля. Сначала установите утилиту, входящую в пакет apache2-utils:

  1. sudo apt-get install apache2-utils

Затем сгенерируйте пароль с помощью htpasswd. Замените secure_password паролем, который вы хотите использовать для администратора Traefik:

  1. htpasswd -nb admin secure_password

Вывод из программы будет выглядеть так:

Output
admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/

Вы будете использовать эти выходные данные в файле конфигурации Traefik для настройки базовой HTTP-аутентификации для панели мониторинга и проверки работоспособности Traefik. Скопируйте всю строку вывода, чтобы вы могли вставить ее позже.

Чтобы настроить сервер Traefik, мы создадим новый файл конфигурации с именем traefik.toml, используя формат TOML. TOML — это язык конфигурации, аналогичный INI-файлам, но стандартизированный. Этот файл позволяет нам настроить сервер Traefik и различные интеграции или провайдеров, которые мы хотим использовать. В этом руководстве мы будем использовать три доступных провайдера Traefik: api, docker и acme, который используется для поддержки TLS с использованием Let's Encrypt. .

Откройте новый файл в nano или в вашем любимом текстовом редакторе:

  1. nano traefik.toml

Во-первых, добавьте две именованные точки входа, http и https, к которым по умолчанию будут иметь доступ все серверные части:

defaultEntryPoints = ["http", "https"]

Точки входа http и https мы настроим позже в этом файле.

Затем настройте поставщика api, который предоставит вам доступ к интерфейсу панели инструментов. Сюда вы вставите вывод команды htpasswd:

...
[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]

[api]
entrypoint="dashboard"

Панель инструментов — это отдельное веб-приложение, которое будет работать в контейнере Traefik. Мы настроили панель инструментов для работы на порту 8080.

Раздел entrypoints.dashboard настраивает, как мы будем подключаться к поставщику api, а раздел entrypoints.dashboard.auth.basic настраивает Базовая HTTP-аутентификация для панели управления. Используйте выходные данные только что выполненной команды htpasswd для значения записи users. Вы можете указать дополнительные логины, разделив их запятыми.

Мы определили нашу первую entryPoint, но нам нужно определить другие для стандартной связи HTTP и HTTPS, которые не направлены на поставщика api. Раздел 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 = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

Этот раздел называется acme, потому что ACME — это название протокола, используемого для связи с Let’s Encrypt для управления сертификатами. Служба Let’s Encrypt требует регистрации с действительным адресом электронной почты, поэтому, чтобы Traefik генерировал сертификаты для наших хостов, установите ключ email на свой адрес электронной почты. Затем мы указываем, что будем хранить информацию, которую получим от Let’s Encrypt, в файле JSON с именем acme.json. Ключ entryPoint должен указывать на точку входа, обрабатывающую порт 443, который в нашем случае является точкой входа https.

Ключ onHostRule указывает, как Traefik должен создавать сертификаты. Мы хотим получить наши сертификаты, как только будут созданы наши контейнеры с указанными именами хостов, и это то, что сделает параметр onHostRule.

Раздел acme.httpChallenge позволяет указать, как Let’s Encrypt может проверить необходимость создания сертификата. Мы настраиваем его для обслуживания файла как части задачи через точку входа http.

Наконец, давайте настроим провайдер docker, добавив в файл следующие строки:

...
[docker]
domain = "your_domain"
watch = true
network = "web"

Поставщик docker позволяет Traefik выступать в качестве прокси-сервера перед контейнерами Docker. Мы настроили поставщика для отслеживания новых контейнеров в сети web (которую мы скоро создадим) и предоставления их как поддоменов your_domain. .

На этом этапе traefik.toml должен иметь следующее содержимое:

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]

[api]
entrypoint="dashboard"

[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

[docker]
domain = "your_domain"
watch = true
network = "web"

Сохраните файл и выйдите из редактора. Со всей этой конфигурацией мы можем запустить Traefik.

Шаг 2 — Запуск контейнера Traefik

Затем создайте сеть Docker, чтобы прокси-сервер мог совместно использовать контейнеры. Сеть Docker необходима, чтобы мы могли использовать ее с приложениями, которые запускаются с помощью Docker Compose. Назовем эту сеть web.

  1. docker network create web

Когда контейнер Traefik запустится, мы добавим его в эту сеть. Затем мы можем добавить дополнительные контейнеры в эту сеть позже, чтобы Traefik мог использовать прокси.

Затем создайте пустой файл, в котором будет храниться наша информация Let’s Encrypt. Мы поместим это в контейнер, чтобы Traefik мог его использовать:

  1. touch acme.json

Traefik сможет использовать этот файл только в том случае, если пользователь root внутри контейнера имеет уникальный доступ для чтения и записи к нему. Для этого заблокируйте разрешения на acme.json, чтобы только владелец файла имел разрешение на чтение и запись.

  1. chmod 600 acme.json

Как только файл будет передан в Docker, владелец автоматически изменится на пользователя root внутри контейнера.

Наконец, создайте контейнер Traefik с помощью этой команды:

  1. docker run -d \
  2. -v /var/run/docker.sock:/var/run/docker.sock \
  3. -v $PWD/traefik.toml:/traefik.toml \
  4. -v $PWD/acme.json:/acme.json \
  5. -p 80:80 \
  6. -p 443:443 \
  7. -l traefik.frontend.rule=Host:monitor.your_domain \
  8. -l traefik.port=8080 \
  9. --network web \
  10. --name traefik \
  11. traefik:1.7-alpine

Команда немного длинная, поэтому давайте разберем ее.

Мы используем флаг -d для запуска контейнера в фоновом режиме в качестве демона. Затем мы делимся нашим файлом docker.sock с контейнером, чтобы процесс Traefik мог прослушивать изменения в контейнерах. Мы также совместно используем файл конфигурации traefik.toml и файл acme.json, который мы создали в контейнере.

Затем мы сопоставляем порты :80 и :443 нашего хоста Docker с теми же портами в контейнере Traefik, чтобы Traefik получал весь HTTP- и HTTPS-трафик на сервер.

Затем мы настраиваем две метки Docker, которые указывают Traefik направлять трафик на имя хоста monitor.your_domain на порт :8080 внутри контейнера Traefik, раскрывая панель мониторинга.

Мы устанавливаем сеть контейнера на web и называем контейнер traefik.

Наконец, мы используем образ traefik:1.7-alpine для этого контейнера, потому что он маленький.

ENTRYPOINT образа Docker — это команда, которая всегда запускается при создании контейнера из образа. В этом случае команда представляет собой двоичный файл traefik внутри контейнера. Вы можете передать дополнительные аргументы этой команде при запуске контейнера, но мы настроили все наши параметры в файле traefik.toml.

Когда контейнер запущен, у вас теперь есть панель мониторинга, к которой вы можете получить доступ, чтобы увидеть состояние своих контейнеров. Вы также можете использовать эту панель управления для визуализации внешних и внутренних интерфейсов, зарегистрированных Traefik. Получите доступ к панели мониторинга, указав в браузере https://monitor.ваш_домен. Вам будет предложено ввести имя пользователя и пароль, которые являются admin и паролем, который вы настроили на шаге 1.

После входа в систему вы увидите примерно такой интерфейс:

Пока не на что смотреть, но оставьте это окно открытым, и вы увидите, как содержимое меняется, когда вы добавляете контейнеры для работы с Traefik.

Теперь у нас запущен прокси-сервер Traefik, он настроен для работы с Docker и готов отслеживать другие контейнеры Docker. Давайте запустим несколько контейнеров, для которых Traefik будет выступать в качестве прокси.

Шаг 3 — Регистрация контейнеров в Traefik

Запустив контейнер Traefik, вы готовы запускать приложения за ним. Давайте запустим следующие контейнеры позади Traefik:

  1. Блог, использующий официальное изображение Wordpress.
  2. Сервер управления базой данных, использующий официальный образ администратора.

Мы будем управлять обоими этими приложениями с помощью Docker Compose, используя файл docker-compose.yml. Откройте файл docker-compose.yml в своем редакторе:

  1. nano docker-compose.yml

Добавьте следующие строки в файл, чтобы указать версию и сети, которые мы будем использовать:

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

Мы используем Docker Compose версии 3, поскольку это новейшая основная версия формата файла Compose.

Чтобы Traefik распознал наши приложения, они должны быть частью одной сети, и, поскольку мы создали сеть вручную, мы подтягиваем ее, указав сетевое имя web и установив external на true. Затем мы определяем другую сеть, чтобы мы могли подключить наши открытые контейнеры к контейнеру базы данных, который мы не будем раскрывать через Traefik. Мы назовем эту сеть internal.

Далее мы определим каждый из наших сервисов по одному. Начнем с контейнера blog, в основе которого лежит официальный образ WordPress. Добавьте эту конфигурацию в файл:

version: "3"
...

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

Ключ environment позволяет указать переменные среды, которые будут установлены внутри контейнера. Не устанавливая значение для WORDPRESS_DB_PASSWORD, мы сообщаем Docker Compose, что нужно получить значение из нашей оболочки и передать его при создании контейнера. Мы определим эту переменную среды в нашей оболочке перед запуском контейнеров. Таким образом, мы не прописываем пароли в конфигурационный файл.

В разделе labels вы указываете значения конфигурации для Traefik. Метки Docker ничего не делают сами по себе, но Traefik читает их, поэтому знает, как обращаться с контейнерами. Вот что делает каждая из этих меток:

  • traefik.backend указывает имя серверной службы в Traefik (которое указывает на фактический контейнер blog).
  • traefik.frontend.rule=Host:blog.ваш_домен указывает Traefik проверить запрошенный хост и проверить, соответствует ли он шаблону блога. your_domain, он должен направлять трафик в контейнер blog.
  • traefik.docker.network=web указывает, в какой сети следует искать Traefik, чтобы найти внутренний IP-адрес для этого контейнера. Поскольку у нашего контейнера Traefik есть доступ ко всей информации Docker, он потенциально может использовать IP-адрес для внутренней сети, если мы не укажем это.
  • traefik.port указывает открытый порт, который Traefik должен использовать для маршрутизации трафика в этот контейнер.

При такой конфигурации весь трафик, отправляемый на порт 80 нашего хоста Docker, будет направляться в контейнер blog.

Мы назначаем этот контейнер двум разным сетям, чтобы Traefik мог найти его через сеть web и мог взаимодействовать с контейнером базы данных через сеть 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 или внешнего мира, поэтому мы назначаем этот контейнер только для внутренней сети. Поскольку у Traefik есть доступ к сокету Docker, процесс по-прежнему будет предоставлять внешний интерфейс для контейнера mysql по умолчанию, поэтому мы добавим метку traefik.enable=false в укажите, что Traefik не должен предоставлять доступ к этому контейнеру.

Наконец, добавьте эту конфигурацию, чтобы определить контейнер администратора:

services:
...
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

Этот контейнер основан на официальном образе администратора. Конфигурация network и depends_on для этого контейнера точно соответствует тому, что мы используем для контейнера blog.

Однако, поскольку мы направляем весь трафик на порт 80 на нашем хосте Docker непосредственно в контейнер blog, нам нужно настроить этот контейнер по-другому, чтобы трафик сделайте это в нашем контейнере adminer. Строка traefik.frontend.rule=Host:db-admin.your_domain указывает Traefik проверить запрошенный хост. Если он соответствует шаблону db-admin.your_domain, Traefik направит трафик в контейнер adminer.

На этом этапе docker-compose.yml должен иметь следующее содержимое:

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

Сохраните файл и выйдите из текстового редактора.

Затем установите значения в вашей оболочке для переменных WORDPRESS_DB_PASSWORD и MYSQL_ROOT_PASSWORD, прежде чем запускать свои контейнеры:

  1. export WORDPRESS_DB_PASSWORD=secure_database_password
  2. export MYSQL_ROOT_PASSWORD=secure_database_password

Замените secure_database_password на желаемый пароль базы данных. Не забудьте использовать один и тот же пароль для WORDPRESS_DB_PASSWORD и MYSQL_ROOT_PASSWORD.

Установив эти переменные, запустите контейнеры с помощью docker-compose:

  1. docker-compose up -d

Теперь еще раз взгляните на панель администратора Traefik. Вы увидите, что теперь есть backend и frontend для двух открытых серверов:

Перейдите к blog.your_domain, заменив your_domain своим доменом. Вы будете перенаправлены на соединение TLS и теперь можете завершить настройку Wordpress:

Теперь войдите в Администратор, посетив db-admin.your_domain в своем браузере, снова заменив your_domain своим доменом. Контейнер mysql не открыт для внешнего мира, но контейнер adminer имеет к нему доступ через внутреннюю сеть Docker, которую они совместно используют с помощью имя контейнера mysql в качестве имени хоста.

На экране входа администратора используйте имя пользователя root, используйте mysql для сервера и используйте значение, которое вы установили для MYSQL_ROOT_PASSWORD в качестве пароля. После входа в систему вы увидите пользовательский интерфейс администратора:

Оба сайта теперь работают, и вы можете использовать панель мониторинга по адресу monitor.your_domain, чтобы следить за своими приложениями.

Заключение

В этом руководстве вы настроили Traefik для прокси-запросов к другим приложениям в контейнерах Docker.

Декларативная конфигурация Traefik на уровне контейнера приложений упрощает настройку дополнительных служб, и нет необходимости перезапускать контейнер traefik при добавлении новых приложений в прокси-трафик, поскольку Traefik сразу же замечает изменения через Docker. файл сокета, который он отслеживает.

Чтобы узнать больше о том, что вы можете делать с Traefik, перейдите к официальной документации Traefik.