【问题标题】:How to add a Traefik service to an existing Docker Swarm cluster?如何将 Traefik 服务添加到现有的 Docker Swarm 集群?
【发布时间】:2021-06-13 21:18:24
【问题描述】:

我有一个 Web 应用程序,我可以使用带有 Compose 文件的 Docker Swarm 成功部署它:

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

并由文件描述:

version: "3.8"
services:
  www:
    image: localhost:5000/www.learnintouch
    ports:
      - "81:80"
      - "444:443"
    networks:
      common:
networks:
  common:
    name: common

现在我向它添加一个 Traefik 服务:

version: "3.8"
services:
  traefik:
    image: traefik
    ports:
      - target: 81
        published: 80
        mode: host
      - target: 8080
        published: 8080
        mode: host
      - target: 444
        published: 443
        mode: host
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      labels:
        - traefik.enable=true
        - traefik.docker.network=common
        - traefik.constraint-label=common
        - traefik.docker.lbswarm=true
    command:
      --log.level=DEBUG
      --api.insecure=true
      --providers.docker
      --providers.docker.swarmmode
      --accesslog
      --api.dashboard=true
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
      - "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
  www:
    image: localhost:5000/www.learnintouch
    ports:
      - "81:80"
      - "444:443"
    labels:
      - "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
    networks:
      common:
networks:
  common:
    name: common
  default:
    driver: overlay

容器已部署:

22:49 $ docker ps
CONTAINER ID   IMAGE                                       COMMAND                  CREATED              STATUS                        PORTS                                                                                                                         NAMES
ff38498c061f   localhost:5000/www.learnintouch:latest      "/bin/bash /usr/loca…"   About a minute ago   Up About a minute (healthy)                                                                                                                                 www_learnintouch_www.1.n9mvfo64hp8unzvcau6rws99q
df070019539f   traefik:latest                              "/entrypoint.sh --lo…"   2 minutes ago        Up 2 minutes                  80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:80->81/tcp, :::80->81/tcp, 0.0.0.0:443->444/tcp, :::443->444/tcp   common_traefik.1.t141a053tvcbi0ql5ztbjmfgp

但是端口映射存在一些问题:

common_traefik.1.t141a053tvcb@stephane-pc    | time="2021-06-13T20:52:24Z" level=error msg="service \"common-traefik\" error: port is missing" providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9
common_traefik.1.t141a053tvcb@stephane-pc    | time="2021-06-13T20:52:39Z" level=error msg="service \"www-learnintouch-www\" error: port is missing" providerName=docker container=www-learnintouch-www-n9mvfo64hp8unzvcau6rws99q
common_traefik.1.t141a053tvcb@stephane-pc    | time="2021-06-13T20:53:24Z" level=warning msg="Could not find network named 'common' for container 'common_traefik'! Maybe you're missing the project's prefix in the label? Defaulting to first available network." providerName=docker container=common-traefik-m6sxqj8giwuex2jlbrsgilsm9 serviceName=common-traefik

我没有使用另一个命令手动创建网络,因为在添加 Traefik 服务之前我不需要这样做。

作为Traefik 和网络假人,我希望安装简单,无需手动指定主机名,也无需运行一些外部命令。

在搜索提示后,我找到了这个opened issue,但我不知道该怎么做。

更新:我为所有服务添加了一个端口,如下所示:

labels:
  - "traefik.http.routers.www_learnintouch.rule=Host('www_learnintouch.docker.localhost')"
  - "traefik.http.services.www.loadbalancer.server.port=5000"

但日志仍然显示相同的错误消息。

更新:提供解决方案后的文件:

version: "3.9"
services:
  traefik:
    image: traefik
    networks:
      common:
    ports:
      - target: 81
        published: 80
        mode: host
      - target: 444
        published: 443
        mode: host
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      labels:
        - "traefik.enable=true"
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"
        - "traefik.constraint-label=common"
    command:
      --log.level=DEBUG
      --api.insecure=true
      --providers.docker
      --providers.docker.swarmmode
      --accesslog
      --api.dashboard=true
      --providers.docker.network=common
      --providers.docker.exposedbydefault=false
      --providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "~/dev/docker/projects/common/volumes/traefik/logs:/traefiklog"
      - "~/dev/docker/projects/common/volumes/traefik/rules:/rules"
  logrotate:
    image: localhost:5000/logrotate
    networks:
      common:
    labels:
      - "traefik.enable=false"
    volumes:
      - "~/dev/docker/projects/common/volumes/logs:/usr/local/logrotate/logs"
    user: "${CURRENT_UID}:${CURRENT_GID}"
    environment:
      HOST_USER_ID: ${CURRENT_UID}
      HOST_GROUP_ID: ${CURRENT_GID}
  www:
    image: localhost:5000/www.learnintouch
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.www.loadbalancer.server.port=80"
    networks:
      common:
    volumes:
      - "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/data:/usr/local/learnintouch/www/learnintouch.com/account/data"
      - "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/backup:/usr/local/learnintouch/www/learnintouch.com/account/backup"
      - "~/dev/docker/projects/learnintouch/volumes/engine:/usr/local/learnintouch/engine"
      - "~/dev/docker/projects/common/volumes/letsencrypt/certbot/conf/live/thalasoft.com:/usr/local/learnintouch/letsencrypt"
      - "~/dev/docker/projects/common/volumes/logs:/usr/local/apache/logs"
      - "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"
    user: "${CURRENT_UID}:${CURRENT_GID}"
    environment:
      HOST_USER_ID: ${CURRENT_UID}
      HOST_GROUP_ID: ${CURRENT_GID}
      DB_HOST: mysql
      DB_PORT: 3306
      WWW_LEARNINTOUCH_DB_NAME: db_learnintouch
      WWW_LEARNINTOUCH_DB_USER: learnintouch
      WWW_LEARNINTOUCH_NAME: learnintouch
      WWW_LEARNINTOUCH_DOMAIN: dev.learnintouch.com
      WWW_LEARNINTOUCH_SCHEME: http
      STAFF_EMAIL: mittiprovence@yahoo.se
      NODEJS_SOCKET_PORT: 9001
    deploy:
      replicas: 1
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
        window: 10s
    healthcheck:
      test: curl --fail http://127.0.0.1:80/engine/ping.php || exit 1
      interval: 10s
      timeout: 10s
      retries: 3
networks:
  common:
    name: common
  default:
    driver: overlay

【问题讨论】:

    标签: docker docker-swarm traefik


    【解决方案1】:

    在 docker swarm 模式下,traefik 无法(出于某种原因!?)检测服务正在侦听的端口。

    因此,每个 docker 服务都需要有一个形式的标签:

    "traefik.http.services.www_learnintouch.loadbalancer.server.port=8080"

    --

    我在第一遍中错过了www 服务。

    您需要从 www 中删除 ports 部分,因为 traefik 需要处理入口,并成为实际公开这些端口的服务。

    然后,你还需要将networks: [ common ]添加到traefik,因为它不能在不共享公共网络的情况下进行此路由。

    最后,traefik 默认公开所有服务,因此会为您的 swarm 上的任何和所有服务发出错误,这些服务没有配置完整/最少的 traefik 标签集,包括它自己。出于某种原因,维护人员对这是愚蠢的,应该修复的想法充耳不闻。

    如果我们解决了这些问题,我建议使用如下所示的 traefik 服务:

    version: "3.9"
    services:
      traefik:
        image: traefik
        ports:
          - target: 80
            published: 80
            mode: host
          - target: 443
            published: 443
            mode: host
        networks:
          - common
        deploy:
          mode: global
          placement:
            constraints:
              - node.role == manager
          labels:
            - traefik.enable=true
            - traefik.http.services.traefik.loadbalancer.server.port=8080
        command:
          --log.level=DEBUG
          --api.insecure=true
          --providers.docker
          --providers.docker.swarmmode
          --accesslog
          --api.dashboard=true
          --providers.docker.network=common
          --providers.docker.exposedbydefault=false
          --providers.docker.defaultRule=Host(`{{normalize .Name}}.docker.local`)
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
    

    您的www 服务将是:

     www_learnintouch:
        image: localhost:5000/www.learnintouch
        labels:
          - traefik.enable=true
          - traefik.http.services.www_learnintouch.loadbalancer.server.port=80
        networks:
          common:
    

    【讨论】:

    • 使用--providers.docker.exposedbydefault=false,每一项服务都需要traefik.enable=true 被traefik 考虑。即不要为 logrotate 启用 traefik。除此之外,除非您查看旧日志,否则这些错误毫无意义。在重新申请之前尝试了docker stack rm common
    • 好吧,我的撰写文件片段并不完整,仅涵盖服务,而不是网络定义。网络定义,正如您对“通用”的定义一样,应该保留。
    • 您正在尝试使用“traefik.docker.local”和“www_learnintouch.docker.local”地址访问该站点?我假设你已经做了一些额外的设置来获得这个域上的通配符名称解析返回 127.0.0.1?
    • 对于将请求路由到服务的 traefik,只需将多个条目添加到该服务的主机规则中 - 即将其添加到您的 www 服务标签:` - traefik.http.routers.www_learnintouch.rule =Host("dev.learnintouch.com","www.docker.local")` 或任何其他映射到127.0.0.1
    • 's 不是 traefik 主机规则的有效字符串标记:由于它们被解析为 go-strings,您可以使用 "s 或 `s,'s 用于单个字符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多