Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 4. Traefik и SSL Let's Encrypt: TLS

Опубликовано admin - пт, 10/04/2024 - 23:31

Небольшая статья - продолжение предыдущих трёх статей:

  1. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm
  2. Docker Swarm и N.ginx, PHP. Вебсервер в кластере Docker Swarm. Часть 2. Mysql.
  3. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 3. Traefik

Добавляем бесплатный SSL Let's Encrypt: TLS.

И так создадим в рабочей директории (cd ~/swarmtest/) файл: 

letsencrypt/acme.json, в котором будут содержаться сертификат.

В файл docker-compose.yml внесем изменения:

web1:
    image: nginx
    #ports:
      #- 4001:80
    deploy:
      replicas: 2
      placement:
         constraints: [node.role == manager]
           #- "node.labels.TAG==prod"
      labels:
        - "traefik.enable=true"
        - "traefik.constraint-label=backend"
        - "traefik.http.routers.nginx.rule=Host(`eapsite.ru`) || Host(`www.site.ru`)"
        - "traefik.http.routers.nginx-ssl.rule=Host(`eapsite.ru`) || Host(`www.site.ru`)"
        - "traefik.docker.network=backend"
        - "traefik.http.routers.nginx.entrypoints=http"
        - "traefik.http.routers.nginx-ssl.entrypoints=https"

        - "traefik.http.routers.nginx.middlewares=to-https"
        - "traefik.http.middlewares.to-https.redirectscheme.scheme=https"
        - "traefik.http.middlewares.to-https.redirectscheme.permanent=true"
          #- "traefik.http.routers.nginx.tls=true"
        - "traefik.http.routers.nginx-ssl.tls.certresolver=myresolver"
          #- "traefik.http.routers.nginx.tls.domains[0].main=site.ru"
          #- "traefik.http.routers.nginx.tls.domains[0].sans=*.site.ru"
        - "traefik.http.services.nginx-http.loadbalancer.server.port=80"

Для создания Let's Encrypt: TLS SSL сертификата важна строка:

- "traefik.http.routers.nginx-ssl.tls.certresolver=myresolver"

В ней определяется сервис для получения сертификата. В нашем случае мы определил его в секции command сервиса "traefik":

  traefik:
    image: "traefik:v3.1"
    container_name: "traefik"
    command:
      - --certificatesresolvers.myresolver.acme.httpchallenge=true
      - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=http
        #- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.myresolver.acme.email=mail@rambler.ru
      - --certificatesresolvers.myresolver.acme.storage=/acme.json

Весь листинг:

version: "3.3"

services:

  traefik:
    image: "traefik:v3.1"
    container_name: "traefik"
    command:
      # Enable Docker Swarm  in Traefik, so that it reads labels from Docker services
      - --providers.swarm.endpoint=unix:///var/run/docker.sock
      # Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
      - --providers.swarm.network=backend
        # Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
      - --providers.swarm.constraints=Label(`traefik.constraint-label`, `backend`)
      # Do not expose all Docker services, only the ones explicitly exposed
      - --providers.swarm.exposedbydefault=false
      # Create an entrypoint "http" listening on address 80
      - --entrypoints.http.address=:80
      # Create an entrypoint "https" listening on address 443
      - --entrypoints.https.address=:443
      #- "--log.level=DEBUG"
      - --entryPoints.http.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
      - --entrypoints.http.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
      - --api
      - --certificatesresolvers.myresolver.acme.httpchallenge=true
      - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=http
        #- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.myresolver.acme.email=mail@mail.ru
      - --certificatesresolvers.myresolver.acme.storage=/acme.json
    ports:
    - "8080:8080"
        - target: 80
          published: 80
          protocol: tcp
          mode: host
        - target: 443
          published: 443
          protocol: tcp
          mode: host
      #- "80:80"
      #- "8080:8080"
    deploy:
       replicas: 1
       placement:
            constraints: [node.role == manager]
       labels:
        - traefik.enable=true
        #- traefik.http.routers.traefik-public-http.middlewares=https-redirect
        # traefik-https the actual router using HTTPS
        # Uses the environment variable DOMAIN
        #- traefik.http.routers.traefik-public-https.rule=Host(`${DOMAIN?Variable not set}`)
        #- traefik.http.routers.traefik-public-https.entrypoints=traefik-ui
        #- traefik.http.routers.traefik-public-https.tls=true
        # Use the special Traefik service api@internal with the web UI/Dashboard
        #- traefik.http.routers.backend.service=api@internal
        # Define the port inside of the Docker service to use
        - traefik.constraint-label=backend
        - traefik.docker.network=backend
    # https-redirect middleware to redirect HTTP to HTTPS
        # It can be re-used by other stacks in other Docker Compose files
        - traefik.http.routers.api-http.rule=Host(`traefik.site.ru`)
        - traefik.http.routers.api-http.middlewares=redirect-to-https
        - traefik.http.routers.api-https.rule=Host(`traefik.site.ru`)
        - traefik.http.routers.api-https.middlewares=redirect-to-https
       #- traefik.http.routers.api-https.tls=true
       #- traefik.http.routers.api-https.tls.certresolver=myresolver
        - traefik.http.routers.api-https.service=api@internal
        - traefik.http.routers.api-http.entrypoints=http
        - traefik.http.routers.api-https.entrypoints=https
        - traefik.http.routers.api.middlewares=auth
        - traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0
        - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
        - traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true
        - traefik.http.services.api.loadbalancer.server.port=80
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt/acme.json:/acme.json"
    networks:
      - backend
  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    deploy:
       labels:
           - "traefik.enable=true"
           - "traefik.http.routers.my-service.rule=Host(`whoami.site.ru`) || Host(`www.whoami.site.ru`)"
           - "traefik.http.routers.my-service.entrypoints=http"
           #- "traefik.http.routers.my-service.middlewares=https-redirect"
           - "traefik.docker.network=backend"
           - "traefik.constraint-label=backend"
           - "traefik.http.services.my-service-http.loadbalancer.server.port=80"
    networks:
      - backend
  web1:
    image: nginx
    #ports:
      #- 4001:80
    deploy:
      replicas: 2
      placement:
         constraints: [node.role == manager]
           #- "node.labels.TAG==prod"
      labels:
        - "traefik.enable=true"
        - "traefik.constraint-label=backend"
        - "traefik.http.routers.nginx.rule=Host(`site.ru`) || Host(`www.site.ru`)"
        - "traefik.http.routers.nginx-ssl.rule=Host(`site.ru`) || Host(`www.site.ru`)"
        - "traefik.docker.network=backend"
        - "traefik.http.routers.nginx.entrypoints=http"
        - "traefik.http.routers.nginx-ssl.entrypoints=https"
        - "traefik.http.routers.nginx.middlewares=to-https"
        - "traefik.http.middlewares.to-https.redirectscheme.scheme=https"
        - "traefik.http.middlewares.to-https.redirectscheme.permanent=true"
        - "traefik.http.routers.my-service.entrypoints=http"
       #- "traefik.http.routers.my-service.middlewares=https-redirect"
        - "traefik.docker.network=backend"
        - "traefik.constraint-label=backend"
        - "traefik.http.services.my-service-http.loadbalancer.server.port=80"
    networks:
      - backend
  web1:
    image: nginx
    #ports:
      #- 4001:80
    deploy:
      replicas: 2
      placement:
         constraints: [node.role == manager]
           #- "node.labels.TAG==prod"
      labels:
        - "traefik.enable=true"
        - "traefik.constraint-label=backend"
        - "traefik.http.routers.nginx.rule=Host(`site.ru`) || Host(`www.site.ru`)"
        - "traefik.http.routers.nginx-ssl.rule=Host(`site.ru`) || Host(`www.site.ru`)"
        - "traefik.docker.network=backend"
        - "traefik.http.routers.nginx.entrypoints=http"
        - "traefik.http.routers.nginx-ssl.entrypoints=https"

        - "traefik.http.routers.nginx.middlewares=to-https"
        - "traefik.http.middlewares.to-https.redirectscheme.scheme=https"
        - "traefik.http.middlewares.to-https.redirectscheme.permanent=true"
        - "traefik.http.middlewares.to-https.redirectscheme.permanent=true"
          #- "traefik.http.routers.nginx.tls=true"
        - "traefik.http.routers.nginx-ssl.tls.certresolver=myresolver"
          #- "traefik.http.routers.nginx.tls.domains[0].main=site.ru"
          #- "traefik.http.routers.nginx.tls.domains[0].sans=*.site.ru"
        - "traefik.http.services.nginx-http.loadbalancer.server.port=80"
    environment:
          - NGINX_HOST=site.ru
    volumes:
       - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      #- ./nginx/site-ssl.conf:/etc/nginx/conf.d/site-ssl.conf:ro
       - /gluster/volume1/www:/var/www
       - /gluster/volume1/cert:/etc/letsencrypt/live/site.ru
       - ./letsencrypt/acme.json:/acme.json
    links:
       - php
    networks:
       - backend
  php:
        image: docker-test_php:latest
        ports:
          - 9001:9001
        deploy:
            placement:
              constraints: [node.role == manager]
            replicas: 1
            resources:
              limits:
               cpus: '0.1'
                memory: 200M
        volumes:
          #- /mnt:/var/www
           - /gluster/volume1/www:/var/www
        networks:
          - backend
  database:
      #container_name: database
      image: mysql
      #restart: always
      environment:
        MYSQL_ROOT_PASSWORD: my-secret-pw
        MYSQL_ROOT_HOST: "%"
        MYSQL_DATABASE: swtest_docker
        MYSQL_USER: swtest
        MYSQL_PASSWORD: swtest
      ports:
        - 4307:3306
      deploy:
          labels:
            - "traefik.enable=false"
          replicas: 1
          placement:
              constraints:
                  - "node.labels.TAG==prod"
      volumes:
        - ./data/mysql:/var/lib/mysql
      networks:
          - backend

networks:
  backend:

Запускаем 

docker stack deploy --compose-file docker-compose.yml swarmtest

Результат:

Docker Swarm Traefik SSL Let Encrypt

Взаимосвязанные материалы

# 1. Типичный пример Docker с Nginx и SSL (воскресенье, октября 6, 2024 - 15:33 ),
Типичный пример быстрой настройки Docker и Nginx c доступом по https. читать...
# 2. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 4. Traefik и SSL Let's Encrypt: TLS (пятница, октября 4, 2024 - 23:31 ),

Небольшая статья - продолжение предыдущих трёх статей:

читать...
# 3. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 3. Traefik. (четверг, октября 3, 2024 - 12:35 ),
Продолжаем настройку кластера Swarm. В этой статье мы попробуем добавить Traefik к уже существующему стэку Docker Swarm. читать...
# 4. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 2. Mysql. (вторник, октября 1, 2024 - 11:53 ),
Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 2. Mysql. В этой статье мы попробуем добавить сервер mysql к уже существующему стэку Docker Swarm. читать...
# 5. Docker Swarm и Nginx, PHP. Вебсервер в кластере Docker Swarm. Часть 1. (понедельник, сентября 23, 2024 - 14:57 ),
С помощью Docker можно быстро развернуть рабочее web приложение с различными настройками и версиями. Docker Swarm выступает инструментом «оркестрации» контейнеров Docker, который позволяет управлять контейнерами как единое целое. читать...
На разработку сайта! Скидки до 20%!