Ненавязчивая локальная разработка с traefik2, docker и letsencrypt

16.05.21

Разработка - DevOps и автоматизация разработки

Перевод статьи по проксированию HTTP траффика до сервисов развернутых в docker контейнерах. Оригинал от 24.09.2020.

Когда дело доходит до разработки сайтов, использующих поддомены, это может быть сложной или скучной задачей, поскольку localhost не является полным доменным именем. Вы не можете просто перейти, к примеру.localhost. Вы либо постоянно редактируете /etc/hosts, либо настраиваете некоторые dnsmasq в своей локальной сети.

До сих пор наиболее часто используемые мной решения были http://lvh.me (на данный момент не работает) - бесплатный сервис, который разрешает себя вместе со всеми поддоменами на localhost, и похожий на него сервис http://nip.io который позволяет кодировать ip-адрес для преобразования в доменное имя 192-168-1-250.nip.io, и, таким образом, позволяет генерировать сертификат letsencrypt для указанного домена.

Это было рабочим решением в течении половины десятилетия, но по мере того, как все больше и больше моих клиентов переходили к обзору pull request (PR) и параллельно выбирали docker или kubernetes в качестве платформы, я все больше и больше ограничивался классическими решениями выше.

 
 О обзоре pull request

То, что я хотел в прошлом году - это воспроизводимый сценарий для реализации собственной локальной среды разработки, которую я могу легко воспроизвести на удаленном сервере для реализации сценариев проверки PR, поддержки некоторых разумных привилегий, таких как валидные SSL сертификаты, некоторые возможности устранения неполадок и так далее.

Давайте рассмотрим подход, который я сейчас использую для клиентов, использующих докеризованные приложения (локальные или swarm) 

 
 О swarm (режим роя)

 

Выбор компонентов для решения

Компоненты

а) docker- классический или в режиме роя. (На моем рабочем ноутбуке у меня есть докер в режиме роя, это не мешает ему также использоваться в качестве автономной среды докера)

б) traefik2 в виде официального образа докера. Traefik-это пограничный маршрутизатор с открытым исходным кодом, который делает публикацию ваших услуг веселой и простой. Он получает запросы от имени вашей системы и выясняет, какие компоненты отвечают за их обработку. Особый интерес для меня представляют два поддерживаемых бэкенда - docker и kubernetes.

в) Поддомен разработки. Для хорошо работающего решения нам нужно выделить какой-то поддомен для разработки, например: `*.lvh.voronenko.net` - указывающий на локальный хост, или `*.preview.project.net` - какой-то подстановочный домен, указывающий на ваш промежуточный сервер.

d) Wildcard сертификат от letsencrypt для организации валидных сертификатов. Хотя на удаленной виртуальной машине traefik может позаботиться о получении валидного сертификата для каждого полного доменного имени для вас, если у вас есть возможность предварительно создать сертификат wildcard - почему бы и нет?
Настроенный домен с указанием на локальный хост, как уже упоминалось `*.lvh.voronenko.net - ... ты должен сам позаботиться об этом.

Wildcard-сертификат — сертификат открытого ключа, который может использоваться с несколькими подобластями домена.

Для генерации сертификатов letsencrypt мой текущий инструмент выбора - это acme.sh - мощный и простой в использовании клиент протокола ACME, написанный исключительно на языке оболочки (оболочка Unix), совместимый с оболочками bash, dash и sh. Помогает управлять установкой, продлением, отзывом SSL-сертификатов. https://github.com/acmesh-official/acme.sh

acme.sh --issue --dns dns_gd -d lvh.voronenko.net -d "*.lvh.voronenko.net"

Обратите внимание, что инструмент также заботится о продлении сертификата, когда это необходимо.
Установка сертификатов в нужную папку также проста, как выполнение сценария оболочки

~/.acme.sh/acme.sh --install-cert -d "${DOMAIN_NAME}" \
        --cert-file $TARGET/cert.pem \
        --key-file  $TARGET/privkey.pem \
        --fullchain-file $TARGET/fullchain.pem

В худшем случае (если вы не проинструктировали acme.sh с командой, что делать при продлении сертификата) - вам нужно будет позаботиться о копировании нового набора сертификатов один раз в 93 дня

e) Какой нибудь инструмент, которым вы можете проверить, что происходит с docker. Есть много хороших консольных инструментов, но если вам нравится вариант с веб-интерфейсом - portainer, безусловно, один из лучших.

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

 

Локальная настройка - настройка traefik для локальной разработки

Нам нужны:

папка "traefik_certs", в которой мы будем хранить предварительно созданный wildcard сертификат (у вас может быть более одного), также здесь traefik будет хранить информацию о собственных сертификатах.

папка "traefik_conf", в которой мы будем хранить части конфигурации traefik, которую мы хотим исключить из docker-compose.

По умолчанию "certificates.toml" сообщает traefik, что у нас есть один предварительно созданный сертификат, который можно найти по указанному пути в папке certs.

 
 о TOML

 

[[tls.certificates]] #first certificate
   certFile = "/certs/fullchain.pem"
   keyFile = "/certs/privkey.pem"

#[[tls.certificates]] #second certificate
#   certFile = "/path/to/other.cert"
#   keyFile = "/path/to/other.key"

Управление через `Makefile" поможет вам создать общую общедоступную сеть для docker, которая будет использоваться traefik для поиска открытых служб и процедур повышения/понижения

 
 о Makefile

 

create-traefik-network-once:
        docker network create traefik-public
up:
        docker-compose up -d
down:
        docker-compose down

и сердце конструкции: основной докер файл с описанием компоновки для traefik, чтобы сделать историю короче, я прокомментирую наиболее важные части конфигурации

 
 о YAML (не путать с YML)

 

version: '3.4'
services:
  traefik:
    image: traefik:v2.1.4
# на моем ноутбуке traefik работает на портах http https по умолчанию
# это позволяет работать с URL-адресами, таким как https://app.lvh.voronenko.net/
    ports:
      - 80:80
      - 443:443
# настройка может быть легко преобразована в развертывание роя
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.id
      labels: []
# /certs и /conf - это выделенные известные каталоги в
# официальном traefik образе.
# для того, чтобы позволить traefik обращаться бэкэнду docker, мы
# сопоставляем внутри сокеты docker.
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik_certs:/certs
      - ./traefik_conf:/conf
    restart: always
# если traefik должен обслуживать реальный кластер роя, следует указать `peram`
#       --docker.swarmmode
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.watch=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/conf/"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.mongo.address=:27017"
      - "--entrypoints.postgres.address=:5432"
      - "--log.level=DEBUG"
      - "--accessLog"
      - "--api"
      - "--metrics"
      - "--metrics.prometheus"
      - "--providers.docker.network=traefik-public"
    networks:
      - default
      - traefik-public
# traefik конфигурируется с помощью метол (labels)
# откройте панель мониторинга traefik по адресу https://traefik.lvh.voronenko.net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.lvh.voronenko.net`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.tls.certresolver=letsencryptresolver"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
# пользовательский интерфейс управления docker, который будет доступен по адресу
# https://docker.lvh.voronenko.net
  portainer:
    image: portainer/portainer
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`docker.lvh.voronenko.net`)"
      - "traefik.http.routers.portainer.entrypoints=web"
      - "traefik.http.routers.portainer-secure.rule=Host(`docker.lvh.voronenko.net`)"
      - "traefik.http.routers.portainer-secure.entrypoints=websecure"
      - "traefik.http.routers.portainer-secure.tls=true"
volumes:
  portainer_data:
networks:
  traefik-public:
    external: true

 

Теперь, если вы запустите настройку, т.е. `docker-compose up -d`, вы получите:

a) traefikUI по адресу https://traefik.lvh.voronenko.net/ - не так много параметров доступных изменения, но хороший вид с высоты птичьего полета на обнаруженные в настоящее время сервисы. Обратите внимание, что эта страница отображается с валиным сертификатом, который вы настроили.

b) PortainerUI по адресу https://docker.lvh.voronenko.net/ - предоставляет подробные внутренние параметры в docker, работающем на вашей машине, контейнерах, службах и т.д.

Обратите внимание, что traefik docker-compose (контейнер) является полностью независимым компонентом вашей системы без прямого отношения к какому-либо проекту, над которым вы в настоящее время работаете. Это означает, что он может постоянно работать на вашем хосте, как и любой другой веб-сервер.

В тот момент, когда вам нужно предоставить какой-либо проект docker, над которым вы в настоящее время работаете, traefik, вам понадобится

а) добавить сервис, доступный за пределами сети `traefik-public`.

б) указать правила обнаружения, например полное доменное имя для службы - "Host(`whoami.lvh.voronenko.net`)"

в) добавить traefik параметры для любой дополнительной конфигурации, такой как перенаправление, авторизация/защита паролем и т.д.

Как только вы запустите такой docker-compose в папке проекта, он сразу же откроется с помощью traefik. Более того - все ваши товарищи по команде, работающие над проектом, имеют точно такую же среду и опыт взаимодействия с ней, но на своих собственных ноутбуках.

Пример настройки контейнера whoami

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    networks:
      - app
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.lvh.voronenko.net`)"
      - "traefik.http.routers.whoami.entrypoints=web"
#      - "traefik.http.middlewares.traefik-auth.basicauth.users=USER:PASSWORD"
#      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
#      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`whoami.lvh.voronenko.net`)"
#      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
networks:
  traefik-public:
    external: true

Ваши сервисы выставляются на выделенные имена, обслуживаемые валидными сертификатами - почти идентичной копией вашей производственной среды.

 

Установка на общедоступном сервере

Настройка экземпляра traefik для удаленной разработки (для развертывания ветки и т.д.) выполняется аналогичным образом, но вам нужно будет лучше защитить свою интеллектуальную собственность (например, вы не хотите, чтобы кто-либо в Интернете просматривал развертывание вашей ветки), а также защитить панели мониторинга portainer и traefik с учетными данными или даже полностью удалить их из общего доступа.

 

Traefik имеет несколько промежуточных программ на выбор https://docs.traefik.io/middlewares/overview/

Наиболее разумными промежуточными программами для рассмотрения были бы

Basic Аутентификация (логин и пароль) https://docs.traefik.io/middlewares/basicauth/

Digest Аутентификация (усиленная Basic ) https://docs.traefik.io/middlewares/digestauth/

Список белых IP https://docs.traefik.io/middlewares/ipwhitelist/

Ограничение количества запросов https://docs.traefik.io/middlewares/ratelimit/

Также для общедоступного сервера traefik позаботится о создании валидных сертификатов, если вы не предоставили предварительно созданный wildcard сертификат.

Кроме того, изменения в настройке `local_server` приведут к активации поставщика сертификатов letsencrypt.
Мы вводим новую сопоставленную папку letsencrypt для хранения автоматически полученных сертификатов.

дополнение в docker-compose.yml

   volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik_certs:/certs
      - ./traefik_conf:/conf
      - ./letsencrypt:/letsencrypt

и мы дополнительно должны активировать провайдера letsencrypt acme в traefik

labels:
      - "--certificatesResolvers.letsencrypt.acme.email=<LETSENCRYPT_MAIL_ADDRESS>"
      - "--certificatesResolvers.letsencrypt.acme.tlsChallenge=true"
      - "--certificatesResolvers.letsencrypt.acme.httpChallenge=true"
      - "--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=web"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"

Тем не менее, я рекомендую, по крайней мере, для хоста, служащего в качестве предварительного просмотра развертывания ветви, предварительно создать wildcard сертификат.
Совершенно бесполезно генерировать новый сертификат для каждой новой развернутой ветви (branchname.preview.voronenko.net)

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

labels:
      - traefik.http.routers.whoami.tls.certresolver=letsencrypt

 

Полный пример для выставленного сервиса:

whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.preview.voronenko.net`)"
      - "traefik.http.routers.whoami.entrypoints=web"
#      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
#      - "traefik.http.middlewares.traefik-auth.basicauth.users=USER:PASSWORD"
#      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
#      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`whoami.preview.voronenko.net`)"
      - "traefik.http.routers.traefik-secure.tls=true"
      - traefik.http.middlewares.whoami.compress=true
      - traefik.http.routers.whoami.tls.certresolver=letsencrypt
     networks:
       traefik-public

 

Резюме

При описанном подходе вы можете обеспечить ненавязчивую локальную разработку с помощью traefik2, docker и letsencrypt индивидуально, а также для всех ваших товарищей по команде. Владельцы стартапов могут применять "фирменную" среду разработки, например "app.lvh.mystartup.domain".

Решение универсально и хорошо работает с несколькими проектами, включая автономные инструменты, распространяемые в виде контейнера docker.

Вы можете легко расширить подход к общедоступному серверу, реализовав "сервер предварительного просмотра" для тех же компонентов. Traefik и docker позволяют вам также вводить предварительные просмотры PR в разумные сроки (в течение дня).

Упомянутые в статье примеры можно попробовать по адресу https://github.com/Voronenko/traefik2-compose-template

`local_server`- это пример среды разработки на вашем локальном хосте, т. е. https://someapp.lvh.voronenko.net/

`public_server` - это пример среды, которую можно развернуть на общедоступном сервере. 

 

От переводчика:

Переводил через translate c правками для сохранения сути статьи. Буду рад разумной критике и правкам по стилистике.

Благодарю за внимание.

См. также

Автотесты для типовых конфигураций ERP Управление предприятием 2 и Комплексная автоматизация 2 (для vanessa automation)

Тестирование QA DevOps и автоматизация разработки Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Бухгалтерский учет Налоговый учет Платные (руб)

Готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарии возможно использовать как для vanessa-automation, так и для СППР. Поддерживаемые версии конфигураций ERP2 и КА2: 2.5.15.111.

2220 руб.

04.07.2022    6982    26    1    

24

Системы контроля версий для 1С-разработчиков.

1С-программирование DevOps и автоматизация разработки Групповая разработка (Git, хранилище) DevOps для 1С Платформа 1С v8.3 Платные (руб)

Основы командной разработки на 1С. Использование систем контроля версий при разработке на платформе 1С:Предприятие 8

4900 руб.

29.06.2022    9455    78    4    

112

Управление сборкой. Расширение для конфигурации СППР

DevOps и автоматизация разработки Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Подсистема «Управление сборкой GLI» предназначена для динамического формирования сборочных линий Gitlab и отслеживания процесса доработок систем на базе1С:Предприятия Позволяет упростить выпуск новых релизов системы, подготовить описание доработок системы. Интегрируется с GitLab API по событиям Push, Merge-request, Pipeline. Уведомляет пользователей о результатах сборки/тестирования сборочных конвейеров через СВ, либо при её недоступности или отсутствию по E-Mail. Поможет при отправке исправлений ошибок в общую базу тестирования, сформирует запросы на слияние в ветку версии только по протестированному и подтверждённому функционалу. Подсистема рассчитана исключительно на клиент - серверную архитектуру тестовых ИБ. Поддерживаемая версии СППР 2.0.4.15, платформа не ниже 8.3.17.1549, 2.0.7.3 / не ниже 8.3.21.1664, начиная с релиза 1.0.4.30 требуется платформа не ниже 8.3.23 рекомендуемый релиз 8.3.23.1997

7000 руб.

26.08.2022    10837    7    5    

30

Автоматическое подтверждение легальности обновления базы или как обновить 100 типовых баз 1С за 5 часов

DevOps и автоматизация разработки Обновление 1С Платформа 1С v8.3 Конфигурации 1cv8 1С:Бухгалтерия 3.0 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Расширение для конфигураций 1С для автоматического подтверждения легальности обновления и выполнения обработчиков обновления при пакетном автоматическом обновлении большого числа баз 1С. А также сам модуль обработки по автоматическому обновлению баз.

2 стартмани

08.05.2019    24464    56    VPanin56    26    

28

Обновляемый список последних статей Инфостарт для профиля Github

Групповая разработка (Git, хранилище) Бесплатно (free)

Не знаете, чем бы таким заполнить свой профиль Github? Заполните его своими статьями на Инфостарт! Этот простой workflow сам соберет список ваших последних статей и будет периодически обновлять его для актуализации данных.

08.04.2024    943    bayselonarrend    2    

31

Процесс разработки с использованием GIT и расширений для 1С:ERP. Без EDT

Групповая разработка (Git, хранилище) Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Доработки 1С:ERP на крупных проектах можно организовать, не внося изменения в саму типовую конфигурацию, а используя только расширения и отдельные «микроконфигурации». Расскажем о том, как это сделать без EDT, используя процесс разработки GitHub Flow.

02.04.2024    4975    Begemoth80    24    

45

Особенности национального Workflow: Github Actions и OneScript

Групповая разработка (Git, хранилище) OneScript Бесплатно (free)

Сегодня мы посмотрим на Github Actions - встроенный инструментарий Github для автоматизации рабочих процессов. Разберем, что это такое, зачем и причем тут OneScript.

25.03.2024    1610    bayselonarrend    3    

38

Автоматизация процесса разработки с помощью сервиса GitFlic

Групповая разработка (Git, хранилище) Бесплатно (free)

GitFlic – первая в России полностью самостоятельная реализация сервиса для хранения репозиториев с исходным кодом. За три года разработки сервис GitFlic стал полноценным инструментом, которым можно заменить GitLab, GitHub и BitBucket. Расскажем о том, как выстроить в GitFlic процесс автоматического тестирования, статического анализа кода и сборки приложений.

05.03.2024    2121    user1989937    6    

16
Оставьте свое сообщение