1. Теория - разбор Traefik

Thank you for reading this post, don't forget to subscribe!

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

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

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

1: Настройка и запуск Traefik

Исполь­зуй­те ути­ли­ту htpasswd, что­бы создать зашиф­ро­ван­ный пароль. Уста­но­ви­те ути­ли­ту, кото­рая вхо­дит в пакет httpd-tools.

yum install -y httpd-tools

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

htpasswd -nb admin secure_password
admin:$apr1$kEG/8JKj$yEXj8vKO7HDvkUMI/SbOO.

Этот вывод исполь­зу­ет­ся в кон­фи­гу­ра­ци­он­ном фай­ле Traefic для настрой­ки базо­вой аутен­ти­фи­ка­ции HTTP в пане­ли мони­то­рин­га Traefik. Ско­пи­руй­те всю стро­ку, что­бы затем вста­вить ее в файл.

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

Открой­те файл:

vi traefik.toml

Перей­ди­те в режим встав­ки, нажав i, а затем добавь­те две име­но­ван­ные точ­ки вхо­да, 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 для дашборда.

Вставь­те вме­сто your_encrypted_password стро­ку, сге­не­ри­ро­ван­ную ути­ли­той htpasswd. Вы може­те ука­зать несколь­ко пар учет­ных дан­ных, раз­де­лив их запятыми.

Итак, мы опре­де­ли­ли первую точ­ку вхо­да, entryPoint, но для стан­дарт­но­го вза­и­мо­дей­ствия HTTP и HTTPS нуж­ны дру­гие точки.

Раз­дел entryPoints настра­и­ва­ет адрес, кото­рый будут слу­шать Traefik и кон­тей­не­ры. Добавь­те в файл строки:

...
[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 для управ­ле­ния сер­ти­фи­ка­та­ми. Что­бы 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. Про­вай­дер будет сле­дить (стро­ка watch) за новы­ми кон­тей­не­ра­ми в сети, кото­рые мы ско­ро созда­дим, и выстав­лять их как суб­до­ме­ны 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"

Сохра­ни­те и закрой­те файл.

 

2: Запуск контейнера Traefik

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

docker network create web

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

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

touch acme.json

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

chmod 600 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.6-alpine

Рас­смот­рим коман­ду по частям:

  • Флаг –d запус­ка­ет кон­тей­нер в фоно­вом режи­ме как демон. Затем коман­да добав­ля­ет в кон­тей­нер файл docker.sock, бла­го­да­ря чему про­цесс Traefik может про­слу­ши­вать изме­не­ния в кон­тей­не­рах. Так­же в кон­тей­нер мож­но поме­стить кон­фи­гу­ра­ци­он­ный файл traefik.toml и acme.json.
  • После это­го пор­ты 80 и 443 хоста Docker под­клю­ча­ют­ся к одно­му и тому же пор­ту в кон­тей­не­ре Traefik. Теперь Traefik полу­ча­ет все запро­сы HTTP и HTTPS.
  • Затем нуж­но уста­но­вить две мет­ки Docker, кото­рые будут направ­лять тра­фик на хост monitor.your_domain по пор­ту :8080 внут­ри кон­тей­не­ра Traefik, откры­вая дашборд.
  • В каче­стве сети кон­тей­не­ра нуж­но ука­зать web. Кон­тей­нер назы­ва­ет­ся traefik.
  • Затем для созда­ния кон­тей­не­ра исполь­зу­ет­ся образ traefik:1.7.6-alpine.

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

После запус­ка кон­тей­не­ра у вас будет даш­борд, с помо­щью кото­ро­го мож­но про­смот­реть состо­я­ние кон­тей­не­ров. Вы так­же може­те исполь­зо­вать эту панель для визу­а­ли­за­ции интер­фей­сов и бэк­эн­дов, кото­рые заре­ги­стри­ро­вал Traefik. Открой­те панель мони­то­рин­га в браузере:

https://monitor.your_domain

Будет пред­ло­же­но вве­сти имя поль­зо­ва­те­ля и пароль адми­ни­стра­то­ра, и пароль (имя – admin, пароль – стро­ка, кото­рую вы сге­не­ри­ро­ва­ли в раз­де­ле 1).

После аутен­ти­фи­ка­ции на экране появит­ся дашборд.

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

Теперь у вас есть прок­си-сер­вер Traefik, настро­ен­ный для вза­и­мо­дей­ствия с Docker и гото­вый управ­лять дру­ги­ми кон­тей­не­ра­ми Docker.

 

3: Добавление контейнеров для Traefik

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

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

Управ­лять эти­ми при­ло­же­ни­я­ми мож­но с помо­щью Docker Compose, исполь­зуя файл docker-compose.yml:

vi docker-compose.yml

Ука­жи­те в фай­ле вер­сии и сеть:

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

Вер­сия 3 Docker Compose – это новей­шая вер­сия фор­ма­та фай­ла 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 опре­де­ля­ет имя сер­ви­са бэкен­да (кото­рый ука­зы­ва­ет на кон­тей­нер blog).
  • traefik.frontend.rule=Host:blog.your_domain иссле­ду­ет запра­ши­ва­е­мый хост и, если он сов­па­да­ет с шаб­ло­ном 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:

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

В резуль­та­те файл будет выгля­деть так:

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 up -d

Сно­ва открой­те панель Traefik. Вы уви­ди­те, что в ней появи­лись новые кон­тей­не­ры, а так­же backend и frontend.

Открой­те в бра­у­зе­ре blog.your_domain (где your_domain – ваш домен). Соеди­не­ние будет пере­на­прав­ле­но на зашиф­ро­ван­ный порт 443. Теперь мож­но закон­чить уста­нов­ку WordPress.

После это­го открой­те в бра­у­зе­ре db-admin.your_domain. Кон­тей­нер mysql не досту­пен в интер­не­те, но кон­тей­нер adminer име­ет доступ к нему через внут­рен­нюю сеть Docker (internal).

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

Оба сай­та теперь рабо­та­ют. Что­бы полу­чить доступ к даш­бор­ду, вве­ди­те monitor.your_domain.

Заключение

Теперь сер­вер Traefik прок­си­ру­ет запро­сы в кон­тей­не­ры при­ло­же­ний Docker.

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