Конечно же, для полноценной работы веб-проектов такого простого окружения недостаточно, почти сразу же возникнет проблема – как разместить несколько сайтов на одном сервере? Казалось бы, какая же это проблема – просто по тому же принципу развернуть еще несколько контейнеров? Вот только 80 порт уже занят. И сертификаты для https тоже нужны – без них тебя уже браузер на сайт может не пустить. Сегодня попытаемся исправить эти недочеты и запустим в контейнере прокси-сервер Traefik, который к тому же еще и сертификаты на наш домен автоматически подтянет.
Давайте разбираться. Основная задача прокси-сервера при работе с веб-серверами заключается в принятии всех запросов на любой из ваших сайтов “на себя”, обработку этих запросов и направление их на нужный ресурс. Суть в том, что в интернет вы выставляется только прокси-сервер, он в свою очередь будет принимать все запросы и распределять их по контейнерам. Таким образом у вас может быть хоть 2, хоть 10 контейнеров с сайтами или веб-приложениями, и каждому можно будет обратиться по доменному имени.
Подобный подход имеет очевидные преимущества, однако имеет один совсем не очевидный недостаток – подключение к каждому контейнеру будет осуществляться из контейнера прокси-сервера, а значит в логах веб-сервера вы не увидите реальных адресов посетителей – только адрес прокси-сервера. Данную особенность стоит учитывать.
Почему будем использовать именно Traefik? Он поставляется в виде крошечного образа, обеспечивает, при необходимости, балансировку нагрузки, позволяет обновлять конфигурацию без перезагрузки и автоматически получает сертификаты для всех доменных имен.
Перейдем к практике
В директории нашего проекта, который мы создавали в прошлой заметке, необходимо создать еще одну директорию – traefik
1
|
mkdir traefik
|
В этой директории необходимо создать два файла – один конфигурационный файл и один json, в котором будут храниться наши сертификаты.
1
2
3
|
touch acme.json
touch traefik.toml
|
В файле acme.json хранятся файлы сертификатов, поэтому для Traefik обязательно нужно заблокировать этот файл – чтобы только root мог читать или изменять его
1
|
chmod 600 acme.json
|
Прежде чем перейти к редактированию конфигурации прокси-сервера, необходимо создать логин и зашифрованный пароль, которые будут использоваться для входа на панель мониторинга. Для этого будем использовать утилиту из пакета apache2-utils.
1
|
sudo apt install apache2—utils
|
Генерируем пароль:
1
|
htpasswd —nb traefik—admin traefik—pass
|
Замените traefik-pass на ваш пароль и запомните вывод утилиты. Выглядеть он будет примерно так:
1
|
traefik—admin:$apr1$pBYiHQTS$7EsgAVDRzWQD6.8gG8OZI.
|
Теперь открываем конфигурационный файл Traefik:
1
|
nano traefik.toml
|
И пишем в него следующее:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#Отключаем дебаг
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, и привести его к следующему виду:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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
|
Разберем все по порядку
В предыдущей статье мы рассмотрели часть конфигурации, поэтому сейчас опишу только изменения.
1
2
3
4
5
|
services:
traefik:
image: traefik:latest
|
Здесь мы описываем создание сервиса Traefik, образ которого берем напрямую с DockerHub.
1
|
command: —docker —docker.domain=ВАШ_ДОМЕН
|
Выполняем команду внутри docker контейнера, указывая домен, с которым работаем
1
2
3
|
networks:
— traefik-proxy
|
Для контейнера Traefik используем отдельную сеть, чтобы прокси-сервер не мог получить доступ к контейнеру с базой данных.
1
2
3
4
5
6
7
|
volumes:
— /var/run/docker.sock:/var/run/docker.sock
— ./traefik/traefik.toml:/traefik.toml
— ./traefik/acme.json:/acme.json
|
Пробрасываем в контейнер сокет Docker и файлы конфигураций.
1
2
3
4
5
|
labels:
— traefik.frontend.rule=Host:ПОДДОМЕН_ДЛЯ_DASHBOARD
— traefik.port=8080
|
Поле labels не хранит переменных окружения, в отличие от environment, но Traefik способен прочитать labels и взять от туда данные, в которых мы указываем поддомен для доступа на панель мониторинга и порт, на котором эта панель должна работать
1
|
container_name: traefik
|
Задаем контейнеру уникальное имя, чтобы не полагаться на генератор имен Docker Compose
1
2
3
|
links:
— apache_php
|
Прилинковываем Traefik к контейнеру с Apache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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, по второй с базой данных.
1
2
3
4
5
6
7
8
9
|
mariadb:
...
labels:
— traefik.enable=false
...
|
Указываем labels сервиса mariadb (базы данных) для Traefik, чтобы он не пытался связываться с контейнером.
1
2
3
4
5
6
7
8
9
|
networks:
traefik-proxy:
external: true
wp-apache-bd:
external: false
|
Создаем сети для связи контейнеров.
На этом все. Сохраняем файл docker-compose.yml и собираем проект:
1
|
docker—compose up —d
|
и получаем полностью готовый к работе веб-сервер, с сертификатами Letsencrypt и автоматическим перенаправлением с http на https.