One place for hosting & domains

      для

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


      Автор выбрал Girls Who Code для получения пожертвования в рамках программы Write for DOnations.

      Введение

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

      Traefik — это обратный прокси с поддержкой Docker, имеющий собственную панель мониторинга. В этом обучающем модуле вы используете Traefik для перенаправления запросов двух разных контейнеров веб-приложений: контейнера WordPress и контейнера Adminer, каждый из которых взаимодействует с базой данных MySQL. Вы настроите Traefik для обслуживания соединений через HTTPS с помощью Let’s Encrypt.

      Предварительные требования

      Для выполнения этого обучающего модуля вам потребуется следующее:

      Шаг 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

      Программа выдаст следующий результат:

      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 или в другом предпочитаемом текстовом редакторе:

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

      traefik.toml

      defaultEntryPoints = ["http", "https"]
      

      Мы настроим точки входа http и https в следующих шагах.

      Затем настройте провайдер api, который дает доступ к интерфейсу информационной панели. Здесь вам нужно вставить результат выполнения команды htpasswd:

      traefik.toml

      ...
      [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:

      traefik.toml

      ...
        [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:

      traefik.toml

      ...
      [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, добавив в файл следующие строки:

      traefik.toml

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

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

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

      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.

      • docker network create web

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

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

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

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

      Затем создайте контейнер 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.your_domain
      • -l traefik.port=8080
      • --network web
      • --name traefik
      • traefik:1.7.2-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.2-alpine для этого контейнера, поскольку он имеет небольшой размер.

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

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

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

      Пустая информационная панель Traefik

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

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

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

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

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

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

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

      docker-compose.yml

      version: "3"
      
      networks:
        web:
          external: true
        internal:
          external: false
      

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

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

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

      docker-compose.yml

      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.your_domain предписывает Traefik проверить запрошенный хост, и если он соответствует шаблону blog.your_domain, перенаправить трафик в контейнер blog.
      • traefik.docker.network=web указывает, в какой сети Traefik следует искать внутренний IP-адрес для этого контейнера. Поскольку у нашего контейнера Traefik есть доступ ко всей информации Docker, он может взять IP-адрес сети internal, если мы не указали этого.
      • traefik.port задает открытый порт, который Traefik следует использовать для перенаправления трафика в этот контейнер.

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

      Мы назначим для этого контейнера две отдельных сети, чтобы Traefik мог находить его через сеть web и чтобы он мог связываться с контейнером базы данных через сеть internal.

      Наконец, ключ depends_on сообщает Docker Compose, что этот контейнер должен запускаться после того, как будут запущены его зависимости. Поскольку для запуска WordPress требуется база данных, мы должны запустить наш контейнер mysql до того, как запустим контейнер blog.

      Теперь настройте службу MySQL, добавив в файл следующую конфигурацию:

      docker-compose.yml

      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:

      docker-compose.yml

      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
      

      Этот контейнер основан на официальном образе Adminer. Конфигурации 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 должен иметь следующее содержание:

      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, прежде чем запускать контейнеры:

      • export WORDPRESS_DB_PASSWORD=secure_database_password
      • export MYSQL_ROOT_PASSWORD=secure_database_password

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

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

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

      Заполненная информационная панель Traefik

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

      Экран настройки WordPress

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

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

      Adminer подключен к базе данных MySQL

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

      Заключение

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

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

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



      Source link