Ненавязчивая локальная разработка с 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 правками для сохранения сути статьи. Буду рад разумной критике и правкам по стилистике.

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

См. также

DevOps для 1С DevOps и автоматизация разработки Программист Стажер Платные (руб)

Данный онлайн-курс (интенсив) предусматривает изучение процессов, инструментов и методик DevOps, их применение при разработке на платформе 1С. 

2500 руб.

20.06.2023    22682    21    4    

321

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

Использования систем контроля версий — стандарт современной разработки. На курсе научимся использованию Хранилища 1С и GIT при разработке на 1С:Предприятие 8. Разберем подходы и приемы коллективной разработки, научимся самостоятельно настраивать системы и ориентироваться в них.

4900 руб.

29.06.2022    12085    104    4    

134

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

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Зарплата и Управление Персоналом 3 и версии КОРП: 3.1.30.57.

2160 руб.

05.08.2024    1360    15    1    

8

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    12679    10    10    

35

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

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

2400 руб.

04.07.2022    8472    38    1    

29

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

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Бухгалтерия предприятие 3.0 и версии КОРП: 3.0.156.30.

1800 руб.

20.01.2022    7844    19    0    

13

Групповая разработка (Git, хранилище) Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда в хранилище одновременно разрабатывают несколько команд, сортировка сделанного и несделанного при формировании релиза и проведение code review по задачам превращаются в непроходимый квест. В таких случаях нужен бранчинг. Расскажем об опыте перехода на новую схему хранения кода для ИТ-департамента.

23.09.2024    3202    kraynev-navi    3    

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