Конечно же, для полноценной работы веб-проектов такого простого окружения недостаточно, почти сразу же возникнет проблема – как разместить несколько сайтов на одном сервере? Казалось бы, какая же это проблема – просто по тому же принципу развернуть еще несколько контейнеров? Вот только 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.