与 Traefik 2.0 的讨论

你能分享一些截图吗?

附件是 Traefik 仪表板的两个截图。它们显示 Discourse 在“服务”中出现了(两次),但在“路由器”中没有任何内容。说实话,我不确定这具体意味着什么,但我注意到了这一点。

编辑:我是一名新的 Discourse 用户,因此没有权限在单篇帖子中发布两张图片,所以我将回复另一张。

今晚需要启动我的 Docker 进行对比,稍后告知大家,或者这里的其他人也可以分享他们的仪表盘进行对比。

你不需要那个,最好切换到 API 并使用 traefik v2.1,所以:
- "traefik.http.routers.traefik_dashboard-router.service=api@internal"
参见 Endless 502 / forwarding when calling dashboard via subdomain #6123 - #5 by ldez - Traefik v2 - Traefik Labs Community Forum

你能把注释删掉吗?

这样我们读起来更容易。
别担心,我也曾被这样告知过:)。
我把注释写在单独的行里,这样我就可以轻松使用 cat traefikV2.yaml | grep -v "#" 生成干净的打印输出。

这是我的仪表板

  1. 仪表板
  2. HTTP 路由
  3. HTTP 服务
  4. HTTP 中间件

好的,花了我几天时间才处理到这里。我已经重新配置了 Traefik,改用 YAML 文件而不是全部写在 docker-compose 中。不过,在重新连接所有组件后,我似乎遇到了相同或类似的问题——我的域名返回 404 错误,在 Traefik 仪表板中,Services(服务)和 routers(路由器)下能看到 discourse 的条目,但 routers 下却什么都没有。

Traefik docker-compose
version: '3'

services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`monitor.example.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=user:redacted"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`monitor.example.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=http"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true
Traefik data/traefik.yml
api:
  dashboard: true

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  http:
    acme:
      email: nick@innomadic.com
      storage: acme.json
      httpChallenge:
        entryPoint: http
containers/app.yml
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"

expose:

params:
  db_default_text_search_config: "pg_catalog.english"

  db_shared_buffers: "128MB"



env:
  LANG: en_US.UTF-8

  UNICORN_WORKERS: 2

  DISCOURSE_HOSTNAME: forum.example.com


  DISCOURSE_DEVELOPER_EMAILS: 'info@example.com'

  DISCOURSE_SMTP_ADDRESS: redacted.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: redacted
  DISCOURSE_SMTP_PASSWORD: "redacted"

  LETSENCRYPT_ACCOUNT_EMAIL: info@example.com


volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

run:
  - exec: echo "Beginning of custom commands"
  - exec: echo "End of custom commands"

labels:
  app_name:                                                                     discourse

  traefik.enable:                                                               true
  traefik.docker.network:                                                       proxy
  traefik.http.routers.discourse.rule:                                          Host(`forum.example.com`)
  traefik.http.routers.discourse.entrypoints:                                   http
  traefik.http.routers.discourse.middlewares:                                   discourse_redirect2https
  traefik.http.services.discourse.loadbalancer.server.port:                     80

  traefik.http.routers.discourse_secure.rule:                                   Host(`forum.example.com`)
  traefik.http.routers.discourse_secure.entrypoints:                            https

  traefik.http.services.discourse_secure.loadbalancer.server.port:              80
  traefik.http.routers.discourse_secure.tls.certresolver:                       tlsChallenge_letsencrypt

  traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme:      https

docker_args:
  - "--network=proxy"
  - "--expose=80"

我想我还运行了 docker network connect proxy 命令,将此容器连接到 traefik 网络。

非常感谢大家帮我看看我漏掉了什么,另外也很想知道我的安全配置是否已经到位。

我不知道你缺了什么。以下是我在 Ansible 中使用 Traefik 启动站点时所做的操作:

        --docker-args "-l traefik.frontend.rule=Host:{{discourse_hostname}} \
        -l traefik.frontend.entryPoints=https \
        -l traefik.backend={{discourse_shortname}} \
        -l traefik.port=80"

然后执行

       ./launcher start {{ discourse_yml }} {{ docker_args }}

将 Traefik 规则添加到 docker_args 而不是 yml 文件中的额外好处是,Traefik 不会关注正在启动的容器。

我想那可能是 Traefik v1 吧?

哦,抱歉。是的,我相当确定那是 Traefik 1,所以我无法提供具体的帮助。

看起来你在 app.yml 中并没有为这些标签设置任何值?我认为你需要设置一个规则,也许还需要一个中间件?

如果你希望在引导过程中不中断服务,就需要像我的示例中那样,使用 ./launcher start 来设置它们。

也许“中间件”就是以前所说的“后端”?你需要做一些事情来确认 Discourse 容器是你想要的那个服务器,然后……还需要做一些其他操作……将某个前端/URL 与相应的后端/服务器连接起来。

它们已设置,但您需要稍微向右滚动才能看到。这只是格式问题。

谢谢

哈哈,抱歉。

好吧,我其实不太懂这些,但在我看来,将你的 discourse@docker 配置为负载均衡器似乎不太合理。

嘿,我想我找到问题了。

我删除了这一行:
# traefik.http.services.discourse_secure.loadbalancer.server.port: 80

但保留了这一行:

traefik.http.services.discourse.loadbalancer.server.port: 80

labels:
  app_name:                                                                     discourse

  #----Traefik lables------------------------
  traefik.enable:                                                               true
  traefik.docker.network:                                                       proxy
   #---HTTP ROUTER SECTION-------------------
  traefik.http.routers.discourse.rule:                                          Host(`forum.example.com`)
    #--HTTP SECTION--------------------------
  traefik.http.routers.discourse.entrypoints:                                   http
  traefik.http.routers.discourse.middlewares:                                   discourse_redirect2https
  traefik.http.services.discourse.loadbalancer.server.port:                     80

   #---HTTPS ROUTER SECTION
  traefik.http.routers.discourse_secure.rule:                                   Host(`forum.example.com`)
    #--HTTPS SECTION
  traefik.http.routers.discourse_secure.entrypoints:                            https

 # traefik.http.services.discourse_secure.loadbalancer.server.port:              80
    #--TLS SECTION
  traefik.http.routers.discourse_secure.tls.certresolver:                       tlsChallenge_letsencrypt

   #---MIDDLEWARE SECTION redirect http to https
  traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme:      https

我不确定当初是怎么弄成这样的,也不明白为什么会这样,但它确实能工作。所以,我使用了我在帖子中发布的所有配置,只做了这一处修改,现在对我而言已经可以正常使用了。

谢谢大家!

这是正确的。
我在配置中添加了以下内容:

#—服务部分:告诉 Traefik 将请求发送到何处
traefik.http.services.discourse.loadbalancer.server.port: 80

这是否让你感到熟悉?
你在这里所做的,是告诉请求应发送给哪个服务(service)以及使用哪个端口。
你也可以通过使用 expose 来解决这个问题,但从安全角度来看,你希望尽可能少地暴露容器的端口。此外,如果你暴露多个端口,Traefik 会默认选择第一个端口,因此使用 loadbalancer 更为清晰。


Traefik 的 data/traefik.yml

我不这样做,因为该路径是默认路径。

你在这里没有使用完整路径,而是使用了默认路径。我不喜欢这样,因为你必须记住该路径。我使用的是 storage: /etc/ssl/certs/letsencrypt/acme.json

我定义了网络,不喜欢默认设置。

providers:
  docker:
    exposedByDefault: false
    network: bridge_proxy_traefikv2

containers/app.yml

你不需要这样做,这已经由 loadbalancer 完成了。

Traefik 的 docker-compose

你可能想给这个网络一个名称,在我的情况下:

networks:
  traefik:
    external:
      name: bridge_proxy_traefikv2

我一直在按照您在这里的建议进行操作。感谢您的回复。

我想指出一点,对于端点,您说可以信任默认设置;而对于存储位置,您却说您不喜欢信任默认设置。:slight_smile:

我确实尝试了您提到的关于 acme.json 的更改:

然而,我的 Traefik 容器随后找不到该文件。日志中显示为错误。因此,我暂时仍将其保留为 acme.json。

不过,我想问一下这个:

您这里不只是在重命名网络,或者给它一个本地化名称吗?我想我在其他配置和本地环境中只是称它为 proxy。它仍然有一个我定义的名称,我只是没有重命名它。至少我是这样理解的。

我还有一个重要的顾虑。我在上面发布“成功!”之后注意到,虽然 HTTPS 正在工作,但我收到了 混合内容 警告。这意味着并非所有内容都已被加密。

我的 Discourse 安装出现了混合内容错误,但我同一服务器上的 WordPress 安装却没有。所以这一定是我的 Discourse 设置特有的问题。

在开发者控制台中,我看到:

在安全页面上加载混合(不安全)显示内容“http://talk.redacted.com/uploads/default/optimized/1X/_129430568242d1b7f853bb13ebea28b3f6af4e7_2_180x180.png”FaviconLoader.jsm:174:19

所以,也许我的重定向没有正常工作?

我在下面附上了相关文件供审查。

Traefik.yml

api:
dashboard: true

entryPoints:
http:
address: “:80”
https:
address: “:443”

providers:
docker:
exposedByDefault: false
network: proxy

certificatesResolvers:
http:
acme:
email: info@private.com
storage: acme.json
httpChallenge:
entryPoint: http

Traefik docker-compose

version: ‘3’

services:
traefik:
image: traefik:v2.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
labels:
- “traefik.enable=true”
- “traefik.http.routers.traefik.entrypoints=http”
- “traefik.http.routers.traefik.rule=Host(monitor.private.com)”
- "traefik.http.middlewares.traefik-auth.basicauth.users=private:private”
- “traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https”
- “traefik.http.routers.traefik.middlewares=traefik-https-redirect”
- “traefik.http.routers.traefik-secure.entrypoints=https”
- “traefik.http.routers.traefik-secure.rule=Host(monitor.private.com)”
- “traefik.http.routers.traefik-secure.middlewares=traefik-auth”
- “traefik.http.routers.traefik-secure.tls=true”
- “traefik.http.routers.traefik-secure.tls.certresolver=http”
- “traefik.http.routers.traefik-secure.service=api@internal”

networks:
proxy:
external: true

app.yml

templates:

  • “templates/postgres.template.yml”
  • “templates/redis.template.yml”
  • “templates/web.template.yml”
  • “templates/web.ratelimited.template.yml”

expose:

params:
db_default_text_search_config: “pg_catalog.english”

db_shared_buffers: “128MB”

env:
LANG: en_US.UTF-8

UNICORN_WORKERS: 2

DISCOURSE_HOSTNAME: talk.private.com

DISCOURSE_DEVELOPER_EMAILS: ‘info@private.com’

LETSENCRYPT_ACCOUNT_EMAIL: info@private.com

volumes:

  • volume:
    host: /var/discourse/shared/standalone
    guest: /shared
  • volume:
    host: /var/discourse/shared/standalone/log/var-log
    guest: /var/log

hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone GitHub - discourse/docker_manager: Plugin for use with discourse docker image · GitHub

run:

  • exec: echo “Beginning of custom commands”
  • exec: echo “End of custom commands”

labels:
app_name: discourse

traefik.enable: true
traefik.docker.network: proxy
traefik.http.routers.discourse.rule: Host(talk.private.com)
traefik.http.routers.discourse.entrypoints: http
traefik.http.routers.discourse.middlewares: discourse_redirect2https
traefik.http.services.discourse.loadbalancer.server.port: 80

traefik.http.routers.discourse_secure.rule: Host(talk.private.com)
traefik.http.routers.discourse_secure.entrypoints: https
traefik.http.routers.discourse_secure.tls: true
traefik.http.routers.discourse_secure.service: discourse
traefik.http.routers.discourse_secure.tls.certresolver: http

traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme: https

docker_args:

  • “–network=proxy”

那么,关于我为何收到混合内容错误,您有什么看法吗?

嗯,有一会儿我还以为 Discourse 变得有自我意识了,因为我在管理员视图中收到了这条通知:

不过,我做了这个更改后仍然收到了混合内容错误。我还尝试了退出登录、清除缓存并重新登录,但问题依旧。

看来我的登录请求仍然被加密了,这算是好事吧,但我需要解决这个混合内容错误。配置信息在之前的帖子中。

另一个更新:混合内容警告现在已消失。我不太清楚原因。我想这可能与 force_https 设置有关,不过,正如我之前提到的,即使我清除了缓存并重新登录,在更改该设置后的约 30 分钟内,页面加载仍未完全正常。

好消息是,我似乎已经在 Traefic 反向代理后成功运行了 Discourse 安装。


问题出在那些通过 HTTP 连接加载的图片上,我也遇到过同样的问题,参见:


你是否正确挂载了卷?Traefik 在路径处理方面可能会让人有些困惑。
例如,我是这样配置的:

volumes:       
  - /etc/ssl/certs/traefik/letsencrypt:/etc/ssl/certs/letsencrypt
  - /opt/traefik/traefik-config.yaml:/etc/traefik/traefik.yaml
  - /etc/passwd.traefik.dashboard:/etc/passwd.BasicAuth.dashboard
  - /etc/passwd.traefik.whoami:/etc/passwd.BasicAuth.whoami

我记不太清了,但当时这么做是有原因的,也许是为了在 CLI 中列出网络时更容易识别。

不,我没有这样挂载。以下是我的 Traefik 的 docker-compose 中的 volumes 部分:

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json

我注意到我的配置中甚至没有提到 Let’s Encrypt,而你的有。我猜你在 docker-compose 目录下创建了那个深层嵌套的文件夹,并将 acme.json 放在了里面?

我注意到的其他问题是,我有 docker.sock 和 localtime。我不确定 localtime 是做什么的,也许 docker.sock 的声明存在安全隐患。需要再查阅一下相关资料。

Let’s Encrypt 证书的创建是由 Traefik 完成的。挂载卷使我可以将其存储在宿主机上,而不是 Docker 容器内。
我记得完成所有挂载工作曾是个大麻烦,我不得不反复通过 docker exec -it 执行各种检查:

  • ls
  • dir
  • vi