Немного о Traefik
В прошлой заметке — вот тут — я рассказывал как, используя Docker compose развернуть простое веб-окружение LAMP.
Конечно же, для полноценной работы веб-проектов такого простого окружения недостаточно, почти сразу же возникнет проблема — как разместить несколько сайтов на одном сервере? Казалось бы, какая же это проблема — просто по тому же принципу развернуть еще несколько контейнеров? Вот только 80 порт уже занят. И сертификаты для https тоже нужны — без них тебя уже браузер на сайт может не пустить.
Сегодня попытаемся исправить эти недочеты и запустим в контейнере прокси-сервер Traefik, который к тому же еще и сертификаты на наш домен автоматически подтянет.
Давайте разбираться. Основная задача прокси-сервера при работе с веб-серверами заключается в принятии всех запросов на любой из ваших сайтов «на себя», обработку этих запросов и направление их на нужный ресурс. Суть в том, что в интернет вы выставляется только прокси-сервер, он в свою очередь будет принимать все запросы и распределять их по контейнерам. Таким образом у вас может быть хоть 2, хоть 10 контейнеров с сайтами или веб-приложениями, и каждому можно будет обратиться по доменному имени.
Подобный подход имеет очевидные преимущества, однако имеет один совсем не очевидный недостаток — подключение к каждому контейнеру будет осуществляться из контейнера прокси-сервера, а значит в логах веб-сервера вы не увидите реальных адресов посетителей — только адрес прокси-сервера. Данную особенность стоит учитывать.
Почему будем использовать именно Traefik? Он поставляется в виде крошечного образа, обеспечивает, при необходимости, балансировку нагрузки, позволяет обновлять конфигурацию без перезагрузки и автоматически получает сертификаты для всех доменных имен. В директории нашего проекта, который мы создавали в прошлой заметке, необходимо создать еще одну директорию — traefik
mkdir traefik
В этой директории необходимо создать два файла — один конфигурационный файл и один json, в котором будут храниться наши сертификаты.
touch acme.json
touch traefik.toml
В файле acme.json хранятся файлы сертификатов, поэтому для Traefik обязательно нужно заблокировать этот файл — чтобы только root мог читать или изменять его
chmod 600 acme.json
Прежде чем перейти к редактированию конфигурации прокси-сервера, необходимо создать логин и зашифрованный пароль, которые будут использоваться для входа на панель мониторинга. Для этого будем использовать утилиту из пакета apache2-utils.
sudo apt install apache2-utils
Генерируем пароль:
htpasswd -nb traefik-admin traefik-pass
Замените traefik-pass на ваш пароль и запомните вывод утилиты. Выглядеть он будет примерно так:
traefik-admin:$apr1$pBYiHQTS$7EsgAVDRzWQD6.8gG8OZI.
Теперь открываем конфигурационный файл Traefik:
nano traefik.toml
И пишем в него следующее:
#Отключаем дебаг
debug = false
#Проверка новых версий
checkNewVersion = true
#Задаем уровень логирования
logLevel = "ERROR"
#Задаем две точки входа для HTTP и HTTPS
defaultEntryPoints = ["https","http"]
#Включаем панель мониторинга Traefik на порту 8080
#используя базовую аутентификацию
[web]
address = ":8080"
[web.auth.basic]
users = ["СГЕНЕРИРОВАНЫЕ РАНЕЕ ЛОГИН И ПАРОЛЬ"]
#Определяем 80 как точку входа HTTP и
#порт 443 для HTTPS
#Включаем автоматический редирект с HTTP на HTTPS
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
#Повторять попытку отправки запроса при ошибке в сети
[retry]
#Определение серверной части конфигурации
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "ВАШ ДОМЕН"
watch = true
exposedbydefault = false
#Регистрация Letsencrypt
#Получение сертификатор используя ACME
[acme]
email = "ВАШ EMAIL"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
Здесь необходимо внести изменения, согласно вашим данным, сохранить изменения в файле и закрыть редактор. Теперь осталось отредактировать файл docker-compose.yml, и привести его к следующему виду:
version: '3'
services:
traefik:
image: traefik:latest
command: --docker --docker.domain=ВАШ_ДОМЕН
ports:
- 80:80
- 443:443
networks:
- traefik-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/traefik.toml:/traefik.toml
- ./traefik/acme.json:/acme.json
labels:
- traefik.frontend.rule=Host:ПОДДОМЕН_ДЛЯ_DASHBOARD
- traefik.port=8080
container_name: traefik
restart: always
links:
- apache_php
apache_php:
build: ./httpd
labels:
- traefik.backend=apache_php
- traefik.frontend.rule=Host:ВАШ_ДОМЕН
- traefik.docker.network=traefik-proxy
- traefik.port=80
volumes:
- ./src:/var/www/html
links:
- mariadb
networks:
- traefik-proxy
- wp-apache-bd
container_name: apache_php
depends_on:
- mariadb
mariadb:
image: mariadb:10.3
restart: always
volumes:
- ./mariadb:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ПАРОЛЬ_ROOT
MYSQL_DATABASE: ИМЯ_БД
MYSQL_USER: ИМЯ_ПОЛЬЗОВАТЕЛЯ_БД
MYSQL_PASSWORD: ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_БД
labels:
- traefik.enable=false
container_name: mariadb
networks:
- wp-apache-bd
networks:
traefik-proxy:
external: true
wp-apache-bd:
external: false
Разберем все по порядку
В предыдущей статье мы рассмотрели часть конфигурации, поэтому сейчас опишу только изменения.
services:
traefik:
image: traefik:latest
Здесь мы описываем создание сервиса Traefik, образ которого берем напрямую с DockerHub.
command: --docker --docker.domain=ВАШ_ДОМЕН
Выполняем команду внутри docker контейнера, указывая домен, с которым работаем
networks:
- traefik-proxy
Для контейнера Traefik используем отдельную сеть, чтобы прокси-сервер не мог получить доступ к контейнеру с базой данных.
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/traefik.toml:/traefik.toml
- ./traefik/acme.json:/acme.json
Пробрасываем в контейнер сокет Docker и файлы конфигураций.
labels:
- traefik.frontend.rule=Host:ПОДДОМЕН_ДЛЯ_DASHBOARD
- traefik.port=8080
Поле labels не хранит переменных окружения, в отличие от environment, но Traefik способен прочитать labels и взять от туда данные, в которых мы указываем поддомен для доступа на панель мониторинга и порт, на котором эта панель должна работать
container_name: traefik
Задаем контейнеру уникальное имя, чтобы не полагаться на генератор имен Docker Compose
links:
- apache_php
Прилинковываем Traefik к контейнеру с Apache
apache_php:
...
labels:
- traefik.backend=apache_php
- traefik.frontend.rule=Host:ВАШ_ДОМЕН
- traefik.docker.network=traefik-proxy
- traefik.port=80
...
networks:
- traefik-proxy
- wp-apache-bd
container_name: apache_php
Назначаем labels для контейнера с Apache, где указываем имя сервиса, к которому будет обращаться Traefik, домен, при обращении к которому, Traefik будет направлять запросы на этот контейнер и сеть, по которой эти запросы будут направляться, а также порт, на котором работает сервис с Apache.
Также указываем сети, с которыми работает Apache — по одной он соединяется с Traefik, по второй с базой данных.
mariadb:
...
labels:
- traefik.enable=false
...
Указываем labels сервиса mariadb (базы данных) для Traefik, чтобы он не пытался связываться с контейнером.
networks:
traefik-proxy:
external: true
wp-apache-bd:
external: false
Создаем сети для связи контейнеров.
На этом все. Сохраняем файл docker-compose.yml и собираем проект:
docker-compose up -d
и получаем полностью готовый к работе веб-сервер, с сертификатами Letsencrypt и автоматическим перенаправлением с http на https.