traefik 是一个开源的反向代理和负载均衡工具,现在官方介绍中将其定位为云原生的边缘路由器,且用了一堆修饰词:简单、自动、高速、全面、开源、产品级、内置监控指标和主流集群技术集成等等。
本文使用的Traefik版本为V2.1.1。中文文档,请参考 https://www.qikqiak.com/traefik-book/

安装Traefik

使用Docker安装

使用官方镜像安装并设置配置参数

  1. docker run -d -p 8080:8080 -p 80:80 --name traefik\
  2. -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik:latest

说明:

  • traefik使用8080和80端口,因为宿主机这两个被使用,所以将这两个映射到其他端口
  • traefik镜像使用最新版本,镜像都是基于 Alpine Linux Official image
  • 默认traefik会寻找/etc/traefik/traefik.toml下的配置文件

因为初次接触traefik,所以对traefik.toml的配置不熟悉,如果上面启动的traefik出现问题,没有关系,可以跳过,往下看,等对traefik有了全面的立即之后,再回过头来配置traefik.toml。

使用docker-compose安装

我们使用 traefik:latest 作为镜像启动traefik 服务。docker-compose.yaml 配置文件如下

  1. version: '3'
  2. services:
  3. traefik:
  4. # The official Traefik docker image
  5. image: traefik:latest
  6. # Enables the web UI and tells Traefik to listen to docker
  7. command: --api.insecure=true --providers.docker
  8. ports:
  9. # The HTTP port
  10. - "80:80"
  11. # The Web UI (enabled by --api.insecure=true)
  12. - "8080:8080"
  13. volumes:
  14. # So that Traefik can listen to the Docker events
  15. - /var/run/docker.sock:/var/run/docker.sock

此时我们使用命令 docker-compose up -d 开启 traefik 服务:

  1. docker-compose up -d

查看状态:

  1. $ docker-compose ps
  2. Name Command State Ports
  3. --------------------------------------------------------------------------------------------
  4. root_traefik_1 /entrypoint.sh --api.insec ... Up 0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp

通过命令行访问traefik对外暴露的http接口:

  1. curl -s "http://localhost:8080/api/rawdata" | python -m json.tool
  2. {
  3. "middlewares": {
  4. "dashboard_redirect@internal": {
  5. "redirectRegex": {
  6. "permanent": true,
  7. "regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
  8. "replacement": "${1}/dashboard/"
  9. },
  10. "status": "enabled",
  11. "usedBy": [
  12. "dashboard@internal"
  13. ]
  14. },
  15. "dashboard_stripprefix@internal": {
  16. "status": "enabled",
  17. "stripPrefix": {
  18. "prefixes": [
  19. "/dashboard/",
  20. "/dashboard"
  21. ]
  22. },
  23. "usedBy": [
  24. "dashboard@internal"
  25. ]
  26. }
  27. },
  28. "routers": {
  29. "api@internal": {
  30. "entryPoints": [
  31. "traefik"
  32. ],
  33. "priority": 2147483646,
  34. "rule": "PathPrefix(`/api`)",
  35. "service": "api@internal",
  36. "status": "enabled",
  37. "using": [
  38. "traefik"
  39. ]
  40. },
  41. "dashboard@internal": {
  42. "entryPoints": [
  43. "traefik"
  44. ],
  45. "middlewares": [
  46. "dashboard_redirect@internal",
  47. "dashboard_stripprefix@internal"
  48. ],
  49. "priority": 2147483645,
  50. "rule": "PathPrefix(`/`)",
  51. "service": "dashboard@internal",
  52. "status": "enabled",
  53. "using": [
  54. "traefik"
  55. ]
  56. },
  57. "traefik-root@docker": {
  58. "rule": "Host(`traefik-root`)",
  59. "service": "traefik-root",
  60. "status": "enabled",
  61. "using": [
  62. "http",
  63. "traefik"
  64. ]
  65. }
  66. },
  67. "services": {
  68. "api@internal": {
  69. "status": "enabled",
  70. "usedBy": [
  71. "api@internal"
  72. ]
  73. },
  74. "dashboard@internal": {
  75. "status": "enabled",
  76. "usedBy": [
  77. "dashboard@internal"
  78. ]
  79. },
  80. "traefik-root@docker": {
  81. "loadBalancer": {
  82. "passHostHeader": true,
  83. "servers": [
  84. {
  85. "url": "http://172.18.0.2:80"
  86. }
  87. ]
  88. },
  89. "serverStatus": {
  90. "http://172.18.0.2:80": "UP"
  91. },
  92. "status": "enabled",
  93. "usedBy": [
  94. "traefik-root@docker"
  95. ]
  96. }
  97. }
  98. }

通过宿主机访问dashboard:http://192.168.56.11:8080/dashboard,可以看到:
image-20191225213250883
可以看到traefik创建了两个Entrypoints

  • HTTP:端口为80
  • TRAEFIK:端口为8080,是Dashboard的入口端点

    测试路由

    接下来我们使用 docker-compose 启动一个简单的 http 服务,docker-compose.yaml 配置文件如下 ``` version: ‘3’ services: traefik:

    The official Traefik docker image

    image: traefik:latest

    Enables the web UI and tells Traefik to listen to docker

    command: —api.insecure=true —providers.docker ports:

    1. # The HTTP port
    2. - "80:80"
    3. # The Web UI (enabled by --api.insecure=true)
    4. - "8080:8080"

    volumes:

    1. # So that Traefik can listen to the Docker events
    2. - /var/run/docker.sock:/var/run/docker.sock

    whoami: image: containous/whoami labels:

    1. # Explicitly tell Traefik to expose this container
    2. - "traefik.enable=true"
    3. # The domain the service will respond to
    4. - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
    5. # Allow request only from the predefined entry point named "http"
    6. - "traefik.http.routers.whoami.entrypoints=http"
  1. - 如果设置了 `--providers.docker.exposedbydefault=false`,则必须设置traefik.enable=true,才会暴露容器给traefik
  2. - 配置了容器的 `labels`,设置该服务的 `Host` `whoami.docker.localhost`,给 `traefik` 提供标记
  3. 创建服务

docker-compose up -d

  1. 查看新创建的服务:

docker-compose ps

  1. Name Command State Ports

root_traefik_1 /entrypoint.sh —api.insec … Up 0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp root_whoami_1 /whoami Up 80/tcp

  1. 再次查看traefik中的路由信息(就会发现服务自动加载进去了)

curl -s “http://localhost:8880/api/rawdata“ | python -m json.tool

  1. 查看dashboard:<br />![image-20191224185315155](https://tva1.sinaimg.cn/large/006tNbRwly1ga80dd5i5qj32440k8788.jpg)<br />此时我们可以通过主机名 `whoami.docker.localhost` 来访问 `whoami` 服务,我们使用 `curl` 做测试

curl -H Host:whoami.docker.localhost http://localhost

  1. 返回内容:

Hostname: ac6e8f48820e IP: 127.0.0.1 IP: 172.18.0.3 RemoteAddr: 172.18.0.2:38018 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.29.0 Accept: / Accept-Encoding: gzip X-Forwarded-For: 172.18.0.1 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 1410f6164208 X-Real-Ip: 172.18.0.1

  1. 服务正常访问。此时如果把 `Host` 配置为自己的域名,则已经可以使用自己的域名来提供服务。<br />单机扩容:

docker-compose up -d —scale whoami=2

  1. 再次访问(就会发现自动负载到两个不同的实例上去了)

$ curl -H Host:whoami.docker.localhost http://localhost Hostname: ac6e8f48820e IP: 127.0.0.1 IP: 172.18.0.3 RemoteAddr: 172.18.0.2:38018 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.29.0 Accept: / Accept-Encoding: gzip X-Forwarded-For: 172.18.0.1 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 1410f6164208 X-Real-Ip: 172.18.0.1

$ curl -H Host:whoami.docker.localhost http://localhost Hostname: 3f64539c40b0 IP: 127.0.0.1 IP: 172.18.0.4 RemoteAddr: 172.18.0.2:44564 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.29.0 Accept: / Accept-Encoding: gzip X-Forwarded-For: 172.18.0.1 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 1410f6164208 X-Real-Ip: 172.18.0.1

  1. 查看dashboard上的**whoami-traefik** Service:<br />![image-20191225213952227](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9at051xyj31fi0pugoe.jpg)<br />可以查看镜像的ip:

$ docker inspect root_whoami_1|grep IPAddress “SecondaryIPAddresses”: null, “IPAddress”: “”, “IPAddress”: “172.18.0.3”,

$ docker inspect root_whoami_2|grep IPAddress “SecondaryIPAddresses”: null, “IPAddress”: “”, “IPAddress”: “172.18.0.4”,

  1. # Traefik配置
  2. ## 静态配置
  3. -
  4. File配置:[https://docs.traefik.io/v2.0/reference/static-configuration/file/](https://docs.traefik.io/v2.0/reference/static-configuration/file/)
  5. -
  6. CLI参数:[https://docs.traefik.io/v2.0/reference/static-configuration/cli/](https://docs.traefik.io/v2.0/reference/static-configuration/cli/)
  7. -
  8. 环境变量:[https://docs.traefik.io/v2.0/reference/static-configuration/env/](https://docs.traefik.io/v2.0/reference/static-configuration/env/)
  9. Traefik在以下为主查找配置文件:
  10. - `/etc/traefik/`
  11. - `$XDG_CONFIG_HOME/`
  12. - `$HOME/.config/`
  13. - `.` (_the working directory_).
  14. 可以通过环境变量参数覆盖配置文件:

traefik —configFile=foo/bar/myconfigfile.toml

  1. ## 动态配置
  2. -
  3. File配置:[https://docs.traefik.io/v2.0/reference/dynamic-configuration/file/](https://docs.traefik.io/v2.0/reference/dynamic-configuration/file/)
  4. -
  5. Docker配置:[https://docs.traefik.io/v2.0/reference/dynamic-configuration/docker/](https://docs.traefik.io/v2.0/reference/dynamic-configuration/docker/)
  6. -
  7. Kubernetes配置:[https://docs.traefik.io/v2.0/reference/dynamic-configuration/kubernetes-crd/](https://docs.traefik.io/v2.0/reference/dynamic-configuration/kubernetes-crd/)
  8. -
  9. Marathon:[https://docs.traefik.io/v2.0/reference/dynamic-configuration/marathon/](https://docs.traefik.io/v2.0/reference/dynamic-configuration/marathon/)
  10. -
  11. Rancher:[https://docs.traefik.io/v2.0/reference/dynamic-configuration/rancher/](https://docs.traefik.io/v2.0/reference/dynamic-configuration/rancher/)
  12. ## traefik.toml
  13. 一个示例traefik.toml内容如下:
#

#

Configuration sample for Traefik v2.

#

For Traefik v1: https://github.com/containous/traefik/blob/v1.7/traefik.sample.toml

#

#
#

全局设置

#

[global] checkNewVersion = true

默认为true

sendAnonymousUsage = false

[serversTransport] insecureSkipVerify = true rootCAs = [“foobar”, “foobar”] maxIdleConnsPerHost = 42 [serversTransport.forwardingTimeouts] dialTimeout = 42 responseHeaderTimeout = 42 idleConnTimeout = 42

#

入口点设置

#

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.https] address = “:443”

[entryPoints.traefik] address = “:8080”

#

日志设置

#

[log]

日志级别,默认 ERROR

level = “DEBUG”

日志默认会打印到stdout,如果不指定filePath,默认使用stdout

filePath = “/data/logs/traefik.log” format = “common”

#

访问日志 配置

#

[accessLog]

日志默认会打印到stdout,如果不指定filePath,默认使用 os.Stdout

filePath = “/data/logs/access.log”

格式目前支持 “json” 和 “common”(默认)

format = “common”

#

API 及控制台配置

#

[api]

Enable the API in insecure mode

#

Optional

Default: true

#

insecure = false

开启控制台(默认开启)

dashboard = true

#

Ping 配置

#

[ping]

入口点名称,默认为traefik

entryPoint = “traefik”

[providers.file] directory = “/etc/traefik/dynamic-conf.toml”

#

Docker 后端配置

#

[providers.docker]

Docker服务后端,默认为unix:///var/run/docker.sock,也可以设置为tcp://10.10.10.10:2375

endpoint = “unix:///var/run/docker.sock”

Default host rule.

#

Optional

Default: “Host({{ normalize .Name }})”

#

defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

对容器默认进行暴露(默认开启)

  1. # 如果关闭选项,则容器不包含 `traefik.enable=true` 标签,就不会被暴露

exposedByDefault = false

  1. ### global

[global] checkNewVersion = true #检查新版本 sendAnonymousUsage = true #发送匿名使用数据

  1. ### serversTransport

[serversTransport] insecureSkipVerify = true rootCAs = [“foobar”, “foobar”] maxIdleConnsPerHost = 42 [serversTransport.forwardingTimeouts] dialTimeout = 42 responseHeaderTimeout = 42 idleConnTimeout = 42

  1. ### entryPoints
  2. 考虑到隐私以及安全,不对外公开的服务可以配置 `Basic Auth``Digest Auth` 或者 `WhiteList`,或者直接搭建 VPN,在内网内进行访问。至于 `Basic Auth` 等,可以参考 **traefik middlewares**<br />![entryPoints](https://docs.traefik.io/assets/img/entrypoints.png)

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.https] address = “:443”

[entryPoints.traefik] address = “:8080”

  1. 上面定义了三个entryPoints,名称分别为webwebsecuretraefik,关于entryPoints完整的定义如下:

Static configuration

[entryPoints] [entryPoints.name] address = “:8888” [entryPoints.name.transport] [entryPoints.name.transport.lifeCycle] requestAcceptGraceTimeout = 42 graceTimeOut = 42 [entryPoints.name.transport.respondingTimeouts] readTimeout = 42 writeTimeout = 42 idleTimeout = 42 [entryPoints.name.proxyProtocol] insecure = true trustedIPs = [“127.0.0.1”, “192.168.0.1”] [entryPoints.name.forwardedHeaders] insecure = true trustedIPs = [“127.0.0.1”, “192.168.0.1”]

  1. ### log

[log]

日志级别,默认 ERROR

level = “DEBUG”

日志默认会打印到stdout,如果不指定filePath,默认使用stdout

filePath = “/data/logs/traefik.log” format = “common” # 格式目前支持 “json” 和 “common”(默认)

  1. ### accessLog

[accessLog]

日志默认会打印到stdout,如果不指定filePath,默认使用 os.Stdout

filePath = “/data/logs/access.log” bufferingSize = 100

格式目前支持 “json” 和 “common”(默认)

format = “common”

过滤日志

[accessLog.filters]
statusCodes = [“200”, “300-302”] retryAttempts = true minDuration = “10ms”

定义日志的字段,有三种模式:keep、drop、redact

[accessLog.fields] defaultMode = “keep” [accessLog.fields.names] “ClientUsername” = “drop” [accessLog.fields.headers] defaultMode = “keep” [accessLog.fields.headers.names] “User-Agent” = “redact” “Authorization” = “drop” “Content-Type” = “keep”

  1. 可用的字段:
  2. |
  3. Field
  4. | Description
  5. |
  6. | --- | --- |
  7. |
  8. `StartUTC`
  9. | The time at which request processing started.
  10. |
  11. |
  12. `StartLocal`
  13. | The local time at which request processing started.
  14. |
  15. |
  16. `Duration`
  17. | The total time taken (in nanoseconds) by processing the response, including the origin server's time but not the log writing time.
  18. |
  19. |
  20. `FrontendName`
  21. | The name of the Traefik frontend.
  22. |
  23. |
  24. `BackendName`
  25. | The name of the Traefik backend.
  26. |
  27. |
  28. `BackendURL`
  29. | The URL of the Traefik backend.
  30. |
  31. |
  32. `BackendAddr`
  33. | The IP:port of the Traefik backend (extracted from `BackendURL`)
  34. |
  35. |
  36. `ClientAddr`
  37. | The remote address in its original form (usually IP:port).
  38. |
  39. |
  40. `ClientHost`
  41. | The remote IP address from which the client request was received.
  42. |
  43. |
  44. `ClientPort`
  45. | The remote TCP port from which the client request was received.
  46. |
  47. |
  48. `ClientUsername`
  49. | The username provided in the URL, if present.
  50. |
  51. |
  52. `RequestAddr`
  53. | The HTTP Host header (usually IP:port). This is treated as not a header by the Go API.
  54. |
  55. |
  56. `RequestHost`
  57. | The HTTP Host server name (not including port).
  58. |
  59. |
  60. `RequestPort`
  61. | The TCP port from the HTTP Host.
  62. |
  63. |
  64. `RequestMethod`
  65. | The HTTP method.
  66. |
  67. |
  68. `RequestPath`
  69. | The HTTP request URI, not including the scheme, host or port.
  70. |
  71. |
  72. `RequestProtocol`
  73. | The version of HTTP requested.
  74. |
  75. |
  76. `RequestLine`
  77. | `RequestMethod` + `RequestPath` + `RequestProtocol`
  78. |
  79. |
  80. `RequestContentSize`
  81. | The number of bytes in the request entity (a.k.a. body) sent by the client.
  82. |
  83. |
  84. `OriginDuration`
  85. | The time taken by the origin server ('upstream') to return its response.
  86. |
  87. |
  88. `OriginContentSize`
  89. | The content length specified by the origin server, or 0 if unspecified.
  90. |
  91. |
  92. `OriginStatus`
  93. | The HTTP status code returned by the origin server. If the request was handled by this Traefik instance (e.g. with a redirect), then this value will be absent.
  94. |
  95. |
  96. `OriginStatusLine`
  97. | `OriginStatus` + Status code explanation
  98. |
  99. |
  100. `DownstreamStatus`
  101. | The HTTP status code returned to the client.
  102. |
  103. |
  104. `DownstreamStatusLine`
  105. | `DownstreamStatus` + Status code explanation
  106. |
  107. |
  108. `DownstreamContentSize`
  109. | The number of bytes in the response entity returned to the client. This is in addition to the "Content-Length" header, which may be present in the origin response.
  110. |
  111. |
  112. `RequestCount`
  113. | The number of requests received since the Traefik instance started.
  114. |
  115. |
  116. `GzipRatio`
  117. | The response body compression ratio achieved.
  118. |
  119. |
  120. `Overhead`
  121. | The processing time overhead caused by Traefik.
  122. |
  123. |
  124. `RetryAttempts`
  125. | The amount of attempts the request was retried.
  126. |
  127. ### metrics
  128. 支持以下几种:
  129. - [Datadog](https://docs.traefik.io/v2.0/observability/metrics/datadog/)
  130. - [InfluxDB](https://docs.traefik.io/v2.0/observability/metrics/influxdb/)
  131. - [Prometheus](https://docs.traefik.io/v2.0/observability/metrics/prometheus/)
  132. - [StatsD](https://docs.traefik.io/v2.0/observability/metrics/statsd/)

[metrics] [metrics.prometheus] buckets = [42.0, 42.0] addEntryPointsLabels = true addServicesLabels = true entryPoint = “foobar” [metrics.datadog] address = “foobar” pushInterval = “10s” addEntryPointsLabels = true addServicesLabels = true [metrics.statsD] address = “foobar” pushInterval = “10s” addEntryPointsLabels = true addServicesLabels = true [metrics.influxDB] address = “foobar” protocol = “foobar” pushInterval = “10s” database = “foobar” retentionPolicy = “foobar” username = “foobar” password = “foobar” addEntryPointsLabels = true addServicesLabels = true

  1. ### tracing
  2. 支持以下几种:
  3. - [Jaeger](https://docs.traefik.io/v2.0/observability/tracing/jaeger/)
  4. - [Zipkin](https://docs.traefik.io/v2.0/observability/tracing/zipkin/)
  5. - [Datadog](https://docs.traefik.io/v2.0/observability/tracing/datadog/)
  6. - [Instana](https://docs.traefik.io/v2.0/observability/tracing/instana/)
  7. - [Haystack](https://docs.traefik.io/v2.0/observability/tracing/haystack/)

[tracing] serviceName = “foobar” spanNameLimit = 42 [tracing.jaeger] samplingServerURL = “foobar” samplingType = “foobar” samplingParam = 42.0 localAgentHostPort = “foobar” gen128Bit = true propagation = “foobar” traceContextHeaderName = “foobar” [tracing.jaeger.collector] endpoint = “foobar” user = “foobar” password = “foobar” [tracing.zipkin] httpEndpoint = “foobar” sameSpan = true id128Bit = true sampleRate = 42.0 [tracing.datadog] localAgentHostPort = “foobar” globalTag = “foobar” debug = true prioritySampling = true traceIDHeaderName = “foobar” parentIDHeaderName = “foobar” samplingPriorityHeaderName = “foobar” bagagePrefixHeaderName = “foobar” [tracing.instana] localAgentHost = “foobar” localAgentPort = 42 logLevel = “foobar” [tracing.haystack] localAgentHost = “foobar” localAgentPort = 42 globalTag = “foobar” traceIDHeaderName = “foobar” parentIDHeaderName = “foobar” spanIDHeaderName = “foobar” baggagePrefixHeaderName = “foobar”

  1. ### api
  2. 暴露API,在生产环境不建议开启。

[api]

如果为true,则会使用名称为traefik的entryPoint,如果该entryPoint不存在,则会自动创建一个名称为traefik端口为8080的entryPoint

insecure = true

开启dashboard,默认为true http://:8080/dashboard/

dashboard = true

开启Endpoints调试,默认为false http://:8080/debug/

debug = true

  1. 如果开启了API,则一个名称为api@internal的特别服务将会被创建,并且可在route中被引用。<br />例如:在Traefik上通过docker定义动态配置:

Dynamic Configuration

labels:

  • “traefik.http.routers.api.rule=Host(traefik.domain.com)”
  • “traefik.http.routers.api.service=api@internal”
  • “traefik.http.routers.api.middlewares=auth”
  • “traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj”
  1. 注意:<br />路由规则必须指定**/api**的请求:

Matches http://traefik.domain.com, http://traefik.domain.com/api

or http://traefik.domain.com/hello

rule = “Host(traefik.domain.com)”

Matches http://api.traefik.domain.com/api or http://domain.com/api

but does not match http://api.traefik.domain.com/hello

rule = “PathPrefix(/api)”

Matches http://traefik.domain.com/api or http://traefik.domain.com/dashboard

but does not match http://traefik.domain.com/hello

rule = “Host(traefik.domain.com) && (PathPrefix(/api) || PathPrefix(/dashboard))”

  1. 所有Endpoints如下:
  2. |
  3. Path
  4. | Description
  5. |
  6. | --- | --- |
  7. |
  8. `/api/http/routers`
  9. | Lists all the HTTP routers information.
  10. |
  11. |
  12. `/api/http/routers/{name}`
  13. | Returns the information of the HTTP router specified by `name`.
  14. |
  15. |
  16. `/api/http/services`
  17. | Lists all the HTTP services information.
  18. |
  19. |
  20. `/api/http/services/{name}`
  21. | Returns the information of the HTTP service specified by `name`.
  22. |
  23. |
  24. `/api/http/middlewares`
  25. | Lists all the HTTP middlewares information.
  26. |
  27. |
  28. `/api/http/middlewares/{name}`
  29. | Returns the information of the HTTP middleware specified by `name`.
  30. |
  31. |
  32. `/api/tcp/routers`
  33. | Lists all the TCP routers information.
  34. |
  35. |
  36. `/api/tcp/routers/{name}`
  37. | Returns the information of the TCP router specified by `name`.
  38. |
  39. |
  40. `/api/tcp/services`
  41. | Lists all the TCP services information.
  42. |
  43. |
  44. `/api/tcp/services/{name}`
  45. | Returns the information of the TCP service specified by `name`.
  46. |
  47. |
  48. `/api/entrypoints`
  49. | Lists all the entry points information.
  50. |
  51. |
  52. `/api/entrypoints/{name}`
  53. | Returns the information of the entry point specified by `name`.
  54. |
  55. |
  56. `/api/overview`
  57. | Returns statistic information about http and tcp as well as enabled features and providers.
  58. |
  59. |
  60. `/api/version`
  61. | Returns information about Traefik version.
  62. |
  63. |
  64. `/debug/vars`
  65. | See the [expvar](https://golang.org/pkg/expvar/) Go documentation.
  66. |
  67. |
  68. `/debug/pprof/`
  69. | See the [pprof Index](https://golang.org/pkg/net/http/pprof/#Index) Go documentation.
  70. |
  71. |
  72. `/debug/pprof/cmdline`
  73. | See the [pprof Cmdline](https://golang.org/pkg/net/http/pprof/#Cmdline) Go documentation.
  74. |
  75. |
  76. `/debug/pprof/profile`
  77. | See the [pprof Profile](https://golang.org/pkg/net/http/pprof/#Profile) Go documentation.
  78. |
  79. |
  80. `/debug/pprof/symbol`
  81. | See the [pprof Symbol](https://golang.org/pkg/net/http/pprof/#Symbol) Go documentation.
  82. |
  83. |
  84. `/debug/pprof/trace`
  85. | See the [pprof Trace](https://golang.org/pkg/net/http/pprof/#Trace) Go documentation.
  86. |
  87. ### ping
  88. 开启健康检查,/ping,对应entryPoint名称默认为traefik

[ping] entryPoint = “traefik” #默认为traefik

  1. 可以自定义一个`entryPoint`

[entryPoints] [entryPoints.ping] address = “:8082”

[ping] entryPoint = “ping”

  1. ### providers
  2. 支持的providers
  3. |
  4. Provider
  5. | Type
  6. | Configuration Type
  7. |
  8. | --- | --- | --- |
  9. |
  10. [Docker](https://docs.traefik.io/v2.0/providers/docker/)
  11. | Orchestrator
  12. | Label
  13. |
  14. |
  15. [Kubernetes](https://docs.traefik.io/v2.0/providers/kubernetes-crd/)
  16. | Orchestrator
  17. | Custom Resource
  18. |
  19. |
  20. [Marathon](https://docs.traefik.io/v2.0/providers/marathon/)
  21. | Orchestrator
  22. | Label
  23. |
  24. |
  25. [Rancher](https://docs.traefik.io/v2.0/providers/rancher/)
  26. | Orchestrator
  27. | Label
  28. |
  29. |
  30. [File](https://docs.traefik.io/v2.0/providers/file/)
  31. | Manual
  32. | TOML/YAML format
  33. |
  34. 配置:

[providers]

Configuration加载频率

providers.providersThrottleDuration = 10s

  1. #### Docker
  2. ![Docker](https://docs.traefik.io/assets/img/providers/docker.png)

[providers.docker]

Docker服务后端,默认为unix:///var/run/docker.sock,也可以设置为tcp://10.10.10.10:2375

endpoint = “unix:///var/run/docker.sock”

Default host rule.

#

Optional

Default: “Host({{ normalize .Name }})”

如果没有配置 Rule,将默认通过 .docker.localhost 来发现路由

defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

对容器默认进行暴露(默认开启)

  1. # 如果关闭选项,则容器不包含 `traefik.enable=true` 标签,就不会被暴露

exposedByDefault = false

开启swarmMode模式,默认为 false

swarmMode = false

默认为empty

network = “test”

设置Docker TLS

[providers.docker.tls] ca = “path/to/ca.crt” caOptional = true cert = “path/to/foo.cert” key = “path/to/foo.key” insecureSkipVerify = true

  1. docker-compose的配置中可以这样使用:

version: “3” services: my-container:

  1. # ...
  2. labels:
  3. - traefik.http.routers.my-container.rule=Host(`mydomain.com`)
  1. ![routers](https://docs.traefik.io/assets/img/routers.png)<br />支持的http routers标签:
  • “traefik.http.routers.myrouter.rule=Host(mydomain.com)”
  • “traefik.http.routers.myrouter.entrypoints=ep1,ep2”
  • “traefik.http.routers.myrouter.middlewares=auth,prefix,cb”
  • “traefik.http.routers.myrouter.service=myservice”
  • “traefik.http.routers.myrouter.tls=true”
  • “traefik.http.routers.myrouter.tls.certresolver=myresolver”
  • “traefik.http.routers.myrouter.tls.domains[0].main=foobar.com”
  • “traefik.http.routers.myrouter.tls.domains[0].sans=test.foobar.com,dev.foobar.com”
  • “traefik.http.routers.myrouter.tls.options=foobar”
  • “traefik.http.routers.myrouter.priority=42”
  1. ![services](https://docs.traefik.io/assets/img/services.png)<br />支持的Services标签:
  • “traefik.http.services.myservice.loadbalancer.server.port=8080”
  • “traefik.http.services.myservice.loadbalancer.server.scheme=http”
  • “traefik.http.services.myservice.loadbalancer.passhostheader=true”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo=foobar”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.hostname=foobar.com”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.interval=10”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.path=/foo”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.port=42”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.scheme=http”
  • “traefik.http.services.myservice.loadbalancer.healthcheck.timeout=10”
  • “traefik.http.services.myservice.loadbalancer.sticky=true”
  • “traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly=true”
  • “traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar”
  • “traefik.http.services.myservice.loadbalancer.sticky.cookie.secure=true”
  • “traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval=10”
  1. ![Overview](https://docs.traefik.io/assets/img/middleware/overview.png)<br />支持的Middleware标签:
  • traefik.http.middlewares.my-redirect.redirectscheme.scheme=https
  1. 支持的tcp routers标签:
  • “traefik.tcp.routers.mytcprouter.rule=HostSNI(mydomain.com)”
  • “traefik.tcp.routers.mytcprouter.entrypoints=ep1,ep2”
  • “traefik.tcp.routers.mytcprouter.middlewares=auth,prefix,cb”
  • “traefik.tcp.routers.mytcprouter.service=myservice”
  • “traefik.tcp.routers.mytcprouter.tls=true”
  • “traefik.tcp.routers.mytcprouter.tls.certresolver=myresolver”
  • “traefik.tcp.routers.mytcprouter.tls.domains[0].main=foobar.com”
  • “traefik.tcp.routers.mytcprouter.tls.domains[0].sans=test.foobar.com,dev.foobar.com”
  • “traefik.tcp.routers.mytcprouter.tls.options=foobar”
  • “traefik.tcp.routers.mytcprouter.tls.passthrough=true”
  1. 支持的TCP Services标签
  • “traefik.tcp.services.mytcpservice.loadbalancer.server.port=423”
  • “traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100”
  1. #### File

[providers.file] directory = “/etc/traefik/conf” filename = “dynamic_conf.toml” watch = true debugLogGeneratedTemplate = true

  1. 动态配置文件可以设置如下内容:

[http]

  1. # Add the router
  2. [http.routers]
  3. [http.routers.routerfoo]
  4. rule = "Host(`snitest.com`) && Path(`/foo`)"
  5. [http.routers.routerfoo.tls]
  6. certResolver = "foo"
  7. [http.routers.routerbar]
  8. rule = "Host(`snitest.com`) && Path(`/bar`)"
  9. [http.routers.routerbar.tls]
  10. certResolver = "bar"
  11. [[http.routers.routerbar.tls.domains]]
  12. main = "snitest.com"
  13. sans = ["*.snitest.com"]
  14. # Add the middleware
  15. [http.middlewares]
  16. [http.middlewares.my-basic-auth.basicAuth]
  17. users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
  18. "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
  19. usersFile = "/etc/traefik/.htpasswd"
  20. # Add the service
  21. [http.services]
  22. [http.services.service-foo]
  23. [http.services.service-foo.loadBalancer]
  24. [[http.services.service-foo.loadBalancer.servers]]
  25. url = "http://foo/"
  26. [[http.services.service-foo.loadBalancer.servers]]
  27. url = "http://bar/"

[tls] [[tls.certificates]] certFile = “path/to/cert.crt” keyFile = “path/to/cert.key” stores = [“foobar”, “foobar”]

[[tls.certificates]] certFile = “path/to/cert.crt” keyFile = “path/to/cert.key” stores = [“foobar”, “foobar”] [tls.options] [tls.options.Options0] minVersion = “VersionTLS12” cipherSuites = [“TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”] sniStrict = true [tls.options.Options0.clientAuth] caFiles = [“tests/clientca1.crt”, “tests/clientca2.crt”] clientAuthType = “RequireAndVerifyClientCert” [tls.options.Options1] minVersion = “VersionTLS13” cipherSuites = [“TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”] sniStrict = true [tls.options.Options1.clientAuth] ccaFiles = [“tests/clientca1.crt”, “tests/clientca2.crt”] clientAuthType = “RequireAndVerifyClientCert” [tls.stores] [tls.stores.Store0] [tls.stores.Store0.defaultCertificate] certFile = “path/to/cert.crt” keyFile = “path/to/cert.key” [tls.stores.Store1] [tls.stores.Store1.defaultCertificate] certFile = “path/to/cert.crt” keyFile = “path/to/cert.key”

  1. clientAuth.clientAuthType
  2. - NoClientCert
  3. - RequestClientCert
  4. - RequireAnyClientCert
  5. - VerifyClientCertIfGiven
  6. - RequireAndVerifyClientCert
  7. ### hostResolver
  8. ### certificatesResolvers
  9. 设置证书:

[certificatesResolvers] [certificatesResolvers.CertificateResolver0] [certificatesResolvers.CertificateResolver0.acme] email = “foobar” caServer = “https://acme-staging-v02.api.letsencrypt.org/directory“ storage = “acme.json” keyType = “foobar” [certificatesResolvers.CertificateResolver0.acme.dnsChallenge] provider = “foobar” delayBeforeCheck = 42 resolvers = [“foobar”, “foobar”] disablePropagationCheck = true [certificatesResolvers.CertificateResolver0.acme.httpChallenge] entryPoint = “foobar” [certificatesResolvers.CertificateResolver0.acme.tlsChallenge] [certificatesResolvers.CertificateResolver1] [certificatesResolvers.CertificateResolver1.acme] email = “foobar” caServer = “https://acme-staging-v02.api.letsencrypt.org/directory“ storage = “acme.json” keyType = “foobar” [certificatesResolvers.CertificateResolver1.acme.dnsChallenge] provider = “foobar” delayBeforeCheck = 42 resolvers = [“foobar”, “foobar”] disablePropagationCheck = true [certificatesResolvers.CertificateResolver1.acme.httpChallenge] entryPoint = “foobar” [certificatesResolvers.CertificateResolver1.acme.tlsChallenge]

  1. #### 配置示例
  2. 1、启用acme

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.https] address = “:443”

[certificatesResolvers] [certificatesResolvers.sample] [certificatesResolvers.sample.acme] email = “your-email@your-domain.org” storage = “acme.json” [certificatesResolvers.sample.acme.dnsChallenge] provider = “dnspod” delayBeforeCheck = 42 resolvers = [“sample”] disablePropagationCheck = true

  1. 2docker中设置路由规则标签<br />单域名:

Dynamic configuration

labels:

  • traefik.http.routers.blog.rule=Host(company.com) && Path(/blog)
  • traefik.http.routers.blog.tls=true
  • traefik.http.routers.blog.tls.certresolver=sample
  1. 多域名:

Dynamic configuration

labels:

  • traefik.http.routers.blog.rule=(Host(company.com) && Path(/blog)) || Host(blog.company.org)
  • traefik.http.routers.blog.tls=true
  • traefik.http.routers.blog.tls.certresolver=sample
  1. 或者:

Dynamic configuration

labels:

  • traefik.http.routers.blog.rule=Host(company.com) && Path(/blog)
  • traefik.http.routers.blog.tls=true
  • traefik.http.routers.blog.tls.certresolver=sample
  • traefik.http.routers.blog.tls.domains[0].main=company.org
  • traefik.http.routers.blog.tls.domains[0].sans=*.company.org
  1. 3、也可以在动态配置中设置路由规则

Dynamic configuration

[http.routers] [http.routers.routerfoo] rule = “Host(company.com) && Path(/blog)” [http.routers.routerfoo.tls] certResolver = “sample”

  1. #### ACME Challenges
  2. ACME Challenges有以下几种类型:
  3. - `tlsChallenge`
  4. - `httpChallenge`
  5. - `dnsChallenge`:支持泛域名,支持的`providers` [https://docs.traefik.io/v2.0/https/acme/#providers](https://docs.traefik.io/v2.0/https/acme/#providers)
  6. `dnsChallenge`示例:

[certificatesResolvers.sample.acme]

[certificatesResolvers.sample.acme.dnsChallenge] provider = “digitalocean” delayBeforeCheck = 0

  1. # 示例
  2. ## docker通过traefik.toml部署traefik
  3. 编辑traefik.toml

Static configuration

[global] checkNewVersion = true sendAnonymousUsage = false

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.traefik] address = “:8080”

[log] level = “DEBUG” filePath = “/data/logs/traefik.log” format = “common”

[accessLog] filePath = “/data/logs/access.log” format = “common”

[api] insecure = true dashboard = true

[ping]

[providers] [providers.docker] endpoint = “unix:///var/run/docker.sock” defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

  1. # 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
  2. exposedByDefault = false
  1. 部署:

version: ‘3’

services: traefik: image: traefik:latest ports:

  1. # The HTTP port
  2. - "80:80"
  3. # The Web UI (enabled by --api.insecure=true)
  4. - "8080:8080"
  5. networks:
  6. - traefik
  7. volumes:
  8. - /var/run/docker.sock:/var/run/docker.sock
  9. - ./traefik.toml:/etc/traefik/traefik.toml
  10. - ./logs:/data/logs

networks: traefik: external: true

  1. 需要先创建网络:

docker network create traefik

  1. 访问 [http://192.168.56.11:8080/](http://192.168.56.11:8080/) ,会跳到 [http://192.168.56.11:8080/dashboard/#/](http://192.168.56.11:8080/dashboard/#/) ,可以看到页面如下:<br />![image-20191225214914318](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9b2s4hdwj30yc0u0n3a.jpg)<br />查看HTTP路由:<br />![image-20191225214942483](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9b39bmicj31qs0skwjb.jpg)<br />可以看到有三个HTTP路由规则,名称为XXX@internal,表明这是内部的服务。
  2. - PathPrefix(`/dashboard`) PathPrefix(`/api`) 是在静态配置[api]定义的
  3. - PathPrefix(`/ping`) 是通过静态配置 [ping] 定义的
  4. - traefik这个Entrypoints上有三个访问规则:
  5. - [http://192.168.56.11:8080/api](http://192.168.56.11:8080/api) 访问traefik提供的api
  6. - [http://192.168.56.11:8080/](http://192.168.56.11:8080/) 跳转到dashboard页面
  7. - [http://192.168.56.11:8880/ping](http://192.168.56.11:8880/ping) 健康检查
  8. 访问 [http://192.168.56.11:8080/api/version](http://192.168.56.11:8080/api/version)<br />![image-20191225215026688](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9b40lp5cj30qi0dcta2.jpg)<br />访问ping接口:[http://192.168.56.11:8080/ping](http://192.168.56.11:8080/ping)<br />![image-20191225215046735](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9b4ckrr6j30z00g4q3j.jpg)<br />查看访问日志:

$ tailf logs/access.log 192.168.2.107 - - [24/Dec/2019:11:41:20 +0000] “GET /api/overview HTTP/1.1” 200 341 “-“ “-“ 6 “api@internal” - 0ms 192.168.2.107 - - [24/Dec/2019:11:41:21 +0000] “GET /api/overview HTTP/1.1” 200 341 “-“ “-“ 7 “api@internal” - 0ms 192.168.2.107 - - [24/Dec/2019:11:41:21 +0000] “GET /api/http/routers?search=&status=&per_page=10&page=1 HTTP/1.1” 200 651 “-“ “-“ 8 “api@internal” - 0ms 192.168.2.107 - - [24/Dec/2019:11:41:35 +0000] “GET /ping HTTP/1.1” 200 2 “-“ “-“ 9 “ping@internal” - 0ms

  1. ## 开启prometheus metrics
  2. 修改traefik.yml

Static configuration

[global] checkNewVersion = true sendAnonymousUsage = false

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.traefik] address = “:8080”

[log] level = “DEBUG” filePath = “/data/logs/traefik.log” format = “common”

[accessLog] filePath = “/data/logs/access.log” format = “common”

[api] insecure = true dashboard = true

[ping]

[providers] [providers.docker] endpoint = “unix:///var/run/docker.sock” defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

  1. # 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
  2. exposedByDefault = false

[metrics] [metrics.prometheus]

  1. 访问 [http://192.168.56.11:8080/dashboard/#/](http://192.168.56.11:8080/dashboard/#/)<br />![image-20191225215811386](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9bc3tywpj31cj0u0tcu.jpg)<br />查看路由:<br />![image-20191225215910475](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9bd4c52sj31cg0smdka.jpg)<br />访问:[http://192.168.56.11:8080/metrics](http://192.168.56.11:8080/metrics) ,可以看到<br />![image-20191225215921748](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9bdbw77bj315k0n8n3u.jpg)
  2. ## Traefik开启TLS
  3. traefik.tom如下:

Static configuration

[global] checkNewVersion = true sendAnonymousUsage = false

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.https] address = “:443”

[entryPoints.traefik] address = “:8080”

[log] level = “DEBUG” filePath = “/data/logs/traefik.log” format = “common”

[accessLog] filePath = “/data/logs/access.log” format = “common”

[api] insecure = true dashboard = true

[ping]

[providers] [providers.file] filename = “/etc/traefik/dynamic-conf.toml” watch = true

[providers.docker] endpoint = “unix:///var/run/docker.sock” defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

  1. # 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
  2. exposedByDefault = false

[metrics] [metrics.prometheus]

  1. 主要做以下改动:
  2. -
  3. 添加端口为443entryPoints
  4. -
  5. api.insecure改为false,所以不能通过8080端口访问/api和/dashboard,需要使用443端口通过域名访问,并且通过80端口访问,会跳转到443端口。/ping接口还是通过8080端口访问
  6. - [https://traefik.javachen.xyz/api/version](https://traefik.javachen.xyz/api/version)
  7. - [https://traefik.javachen.xyz/dashboard/#/](https://traefik.javachen.xyz/dashboard/#/)
  8. - [http://192.168.56.11:8080/ping](http://192.168.56.11:8080/ping) 或者 [http://traefik.javachen.xyz:8080/ping](http://traefik.javachen.xyz:8080/ping)
  9. ![image-20191225141243710](https://tva1.sinaimg.cn/large/006tNbRwly1ga8xvr8d06j31sg0ng793.jpg)
  10. -
  11. 添加动态配置文件 dynamic_conf.toml,用于设置动态路由和TLS
  12. 动态配置dynamic-conf.toml 内容如下:

Dynamic configuration

[http.routers.traefik-https] rule = “Host(traefik.javachen.xyz)” entryPoints = [“https”] service = “api@internal” middlewares = [“auth”] [http.routers.traefik-https.tls]

用户:test 密码:test

[http.middlewares.auth.basicAuth] users = [ “test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/“, ]

[tls] [[tls.certificates]] certFile = “/etc/ssl/javachen.xyz.cer” keyFile = “/etc/ssl/javachen.xyz.key” [tls.stores] [tls.stores.default] [tls.stores.default.defaultCertificate] certFile = “/etc/ssl/javachen.xyz.cer” keyFile = “/etc/ssl/javachen.xyz.key”

  1. 需要准备证书:

安装:自动创建 cronjob, 每天 0:00 点自动检测所有的证书

curl https://get.acme.sh | sh source ~/.bashrc

https://console.dnspod.cn/account/token

export DP_Id=”127880” export DP_Key=”6847f9a4cdba562f574fe55944f689e7” acme.sh —issue —dns dns_dp -d javachen.xyz -d *.javachen.xyz

mkdir ssl cp ~/.acme.sh/javachen.xyz/javachen.xyz.cer ssl/ cp ~/.acme.sh/javachen.xyz/javachen.xyz.key ssl/

  1. 修改docker-compose

version: ‘3’

services: traefik: image: traefik:latest ports:

  1. # The HTTP port
  2. - "80:80"
  3. - "443:443"
  4. # The Web UI (enabled by --api.insecure=true)
  5. - "8080:8080"
  6. networks:
  7. - traefik
  8. volumes:
  9. - /var/run/docker.sock:/var/run/docker.sock
  10. - ./traefik.toml:/etc/traefik/traefik.toml
  11. - ./dynamic-conf.toml:/etc/traefik/dynamic-conf.toml
  12. - ./logs:/data/logs
  13. - ./ssl:/etc/ssl

networks: traefik: external: true

  1. 启动:

docker-compose up -d

  1. 查看http路由:<br />![image-20191225221716306](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9bvxbwl8j31bo0u0q83.jpg)<br />访问 [http://traefik.javachen.xyz/](http://traefik.javachen.xyz/) 和 [https://traefik.javachen.xyz/](https://traefik.javachen.xyz/)<br />修改配置文件中api.insecure=false,再次查看http路由:<br />![image-20191225221916691](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9by0pt48j31f40regpr.jpg)<br />访问ping接口<br />![image-20191225221953437](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9bymzuu0j316s0f2t9e.jpg)
  2. ## 给应用配置LetsEncrypt证书
  3. ![traefik-logic.png](http://wiki.xglabc.com/objst/wiki/pzseopefst0gq3r3o7c1u9xv2cpp09s9-traefik-logic.png)<br />修改traefik.tom,启用acme的dnsChallenge:

Static configuration

[global] checkNewVersion = true sendAnonymousUsage = false

[entryPoints] [entryPoints.http] address = “:80”

[entryPoints.https] address = “:443”

[entryPoints.traefik] address = “:8080”

[log] level = “DEBUG” filePath = “/data/logs/traefik.log” format = “common”

[accessLog] filePath = “/data/logs/access.log” format = “common”

[api] insecure = false dashboard = true

[ping]

[providers] [providers.file] filename = “/etc/traefik/dynamic-conf.toml” watch = true

[providers.docker] endpoint = “unix:///var/run/docker.sock” defaultRule = “Host({{ normalize .Name }}.docker.localhost)”

  1. # 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
  2. exposedByDefault = false

[metrics] [metrics.prometheus]

[certificatesResolvers] [certificatesResolvers.sample] [certificatesResolvers.sample.acme] email = “junecloud@163.com” storage = “/etc/traefik/acme.json” caServer = “https://acme-staging-v02.api.letsencrypt.org/directory“ [certificatesResolvers.sample.acme.dnsChallenge] provider = “dnspod” delayBeforeCheck = 42 resolvers = [“sample”] disablePropagationCheck = true

  1. 使用docker-compose安装:

version: ‘3’

services: traefik: image: traefik:latest ports:

  1. # The HTTP port
  2. - "80:80"
  3. - "443:443"
  4. # The Web UI (enabled by --api.insecure=true)
  5. - "8080:8080"
  6. environment:
  7. - DNSPOD_API_KEY="127880,6847f9a4cdba562f574fe55944f689e7"
  8. networks:
  9. - traefik
  10. volumes:
  11. # So that Traefik can listen to the Docker events
  12. - /var/run/docker.sock:/var/run/docker.sock
  13. - ./traefik.toml:/etc/traefik/traefik.toml
  14. - ./dynamic-conf.toml:/etc/traefik/dynamic-conf.toml
  15. - ./acme.json:/etc/traefik/acme.json
  16. - ./logs:/data/logs
  17. - ./ssl:/etc/ssl

whoami: image: containous/whoami labels:

  1. - traefik.enable=true
  2. - traefik.docker.network=traefik
  3. - traefik.http.routers.whoami.rule=Host(`whoami.javachen.xyz`)
  4. - traefik.http.routers.whoami.entrypoints=http
  5. - traefik.http.routers.whoami-https.rule=Host(`whoami.javachen.xyz`)
  6. - traefik.http.routers.whoami-https.entrypoints=https
  7. - traefik.http.routers.whoami-https.tls=true
  8. - traefik.http.routers.whoami-https.tls.certresolver=sample
  9. # http 重定向到 https
  10. - traefik.http.routers.whoami.middlewares=whoami
  11. - traefik.http.middlewares.whoami.redirectscheme.scheme=https
  12. - traefik.http.middlewares.whoami.redirectscheme.port=443
  13. networks:
  14. - traefik

networks: traefik: external: true

  1. 至此traefik的配置工作已经准备好了,可以启动traefik容器了。

touch acme.json

docker-compose up -d

  1. 进行测试:

$ curl -H Host:whoami.javachen.xyz http://127.0.0.1 Found

$ curl -kH Host:whoami.javachen.xyz https://127.0.0.1 Hostname: 7c944d7cadef IP: 127.0.0.1 IP: 172.22.0.3 RemoteAddr: 172.22.0.2:54580 GET / HTTP/1.1 Host: whoami.javachen.xyz User-Agent: curl/7.29.0 Accept: / Accept-Encoding: gzip X-Forwarded-For: 172.22.0.1 X-Forwarded-Host: whoami.javachen.xyz X-Forwarded-Port: 443 X-Forwarded-Proto: https X-Forwarded-Server: aad4e7f1395d X-Real-Ip: 172.22.0.1

  1. 浏览器访问 [http://whoami.javachen.xyz/](http://whoami.javachen.xyz/) 会跳转到 [https://whoami.javachen.xyz/](https://whoami.javachen.xyz/)<br />![image-20191225222647700](https://tva1.sinaimg.cn/large/006tNbRwgy1ga9c5u46qxj316c0jm0x2.jpg)
  2. ## 测试Mongo TCP路由
  3. [https://github.com/containous/slides/tree/master/demo/traefik-v2](https://github.com/containous/slides/tree/master/demo/traefik-v2) 为例子进行测试。<br />1、测试简单TCP路由<br />docker-compose.yml

version: ‘3’ services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --entrypoints.mongo.address=:27017
  5. ports:
  6. - "27017:27017"
  7. - "8080:8080"
  8. volumes:
  9. - /var/run/docker.sock:/var/run/docker.sock

mongo: image: mongo:4.0 hostname: mongo.local labels:

  1. - "traefik.tcp.routers.mongo.rule=HostSNI(`*`)"
  2. - "traefik.tcp.routers.mongo.entrypoints=mongo"
  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mongo.local

  1. 使用mongo客户端连接:

mongo —host mongo.local —port 27017

show dbs exit

  1. 清理:

docker-compose down -v

  1. 其实,可以修改mongo暴露的端口为80

version: ‘3’ services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --entrypoints.http.address=:80
  5. ports:
  6. - "80:80"
  7. - "8080:8080"
  8. volumes:
  9. - /var/run/docker.sock:/var/run/docker.sock

mongo: image: mongo:4.0 hostname: mongo.local labels:

  1. - "traefik.tcp.routers.mongo.rule=HostSNI(`*`)"
  2. - "traefik.tcp.routers.mongo.entrypoints=http"
  1. 使用mongo客户端连接:

mongo —host mongo.local —port 80

show dbs exit

  1. 2、配置TLS<br />docker-compose.yml

version: ‘3’

services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --providers.file.filename=/etc/ssl/traefik-tls.toml
  5. - --entrypoints.mongo.address=:27017
  6. ports:
  7. - "8080:8080"
  8. - "27017:27017"
  9. volumes:
  10. - /var/run/docker.sock:/var/run/docker.sock
  11. - ../ssl:/etc/ssl

mongo1: image: mongo:4.0 hostname: mongo1.local restart: always labels:

  1. - "traefik.tcp.routers.mongo1.rule=HostSNI(`*`)"
  2. - "traefik.tcp.routers.mongo1.tls=true"
  3. - "traefik.tcp.routers.mongo1.entrypoints=mongo"
  1. traefik-tls.toml

[[tls.certificates]] certFile = “/etc/ssl/cert.pem” keyFile = “/etc/ssl/key.pem”

  1. 生成证书:

rm -rf *.pem sh ../ssl/generate-certificates.sh mongo1.local ./

  1. **generate-certificates.sh**内容如下:

!/bin/bash

#

From https://medium.com/@rajanmaharjan/secure-your-mongodb-connections-ssl-tls-92e2addb3c89

set -eu -o pipefail

DOMAINS=”${1}” CERTS_DIR=”${2}” [ -d “${CERTS_DIR}” ] CURRENT_DIR=”$(cd “$(dirname “${0}”)” && pwd -P)”

GENERATION_DIRNAME=”$(echo “${DOMAINS}” | cut -d, -f1)”

rm -rf “${CERTS_DIR}/${GENERATION_DIRNAME:?}” “${CERTS_DIR}/ssl”

echo “== Checking Requirements…” command -v go >/dev/null 2>&1 || echo “Golang is required” command -v minica >/dev/null 2>&1 || go get github.com/jsha/minica >/dev/null

echo “== Generating Certificates for the following domains: ${DOMAINS}…” cd “${CERTS_DIR}” minica —ca-cert “${CURRENT_DIR}/minica.pem” —ca-key=”${CURRENT_DIR}/minica-key.pem” —domains=”${DOMAINS}” mv “${GENERATION_DIRNAME}” “ssl” cat ssl/key.pem ssl/cert.pem > ssl/mongo.pem

echo “== Certificates Generated in the directory ${CERTS_DIR}/ssl”

  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mongo1.local

  1. 使用mongo客户端连接:

Should Error because no TLS

mongo —host mongo1.local —port 27017

Should work

mongo —host mongo1.local —port 27017 —tls —tlsCAFile=./ssl/minica.pem —tlsCertificateKeyFile=./ssl/mongo.pem

show dbs exit

  1. 清理:

docker-compose down -v

  1. 3、配置TCP TLS通过域名访问<br />docker-compose.yml

version: ‘3’

services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --providers.file.filename=/etc/traefik/traefik-tls.toml
  5. - --entrypoints.mongo.address=:27017
  6. ports:
  7. - "8080:8080"
  8. - "27017:27017"
  9. volumes:
  10. - /var/run/docker.sock:/var/run/docker.sock
  11. - ./ssl:/etc/ssl
  12. - ./traefik-tls.toml:/etc/traefik/traefik-tls.toml

mongo1: image: mongo:4.0 hostname: mongo1.local restart: always labels:

  1. - "traefik.tcp.routers.mongo1.rule=HostSNI(`mongo1.local`)"
  2. - "traefik.tcp.routers.mongo1.tls=true"
  3. - "traefik.tcp.routers.mongo1.entrypoints=mongo"

mongo2: image: mongo:4.0 hostname: mongo2.local restart: always labels:

  1. - "traefik.tcp.routers.mongo2.rule=HostSNI(`mongo2.local`)"
  2. - "traefik.tcp.routers.mongo2.tls.passthrough=true"
  3. - "traefik.tcp.routers.mongo2.entrypoints=mongo"
  4. command:
  5. - "mongod"
  6. - "--sslMode=requireSSL"
  7. - "--sslPEMKeyFile=/etc/ssl/mongo.pem"
  8. volumes:
  9. - ./ssl:/etc/ssl
  1. traefik-tls.toml

[[tls.certificates]] certFile = “/etc/ssl/cert.pem” keyFile = “/etc/ssl/key.pem”

  1. 生成证书:

cd ssl rm -rf .pem sh generate-certificates.sh “mongo1.local,mongo2.local” ./ mv certs/ .

  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mongo1.local mongo2.local

  1. 使用mongo客户端连接:

Mongo 1

mongo —host mongo1.local —port 27017 —ssl —sslCAFile=./ssl/minica.pem —sslPEMKeyFile=./ssl/mongo.pem

show dbs use meetup db.movie.insert({“name”:”Traefik-Awesome”}) db.movie.find() show dbs exit

Mongo2

mongo —host mongo2.local —port 27017 —ssl —sslCAFile=./ssl/minica.pem —sslPEMKeyFile=./ssl/mongo.pem

show dbs exit

  1. 清理:

docker-compose down -v

  1. 3、配置TCP HTTP TLS通过域名访问<br />docker-compose.yml

version: ‘3’

services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --providers.file.filename=/etc/traefik/traefik-tls.toml
  5. - --entrypoints.mongo.address=:27017
  6. ports:
  7. - "8080:8080"
  8. - "27017:27017"
  9. volumes:
  10. - /var/run/docker.sock:/var/run/docker.sock
  11. - ./ssl:/etc/ssl
  12. - ./traefik-tls.toml:/etc/traefik/traefik-tls.toml

mongo1: image: mongo:4.0 hostname: mongo1.local restart: always labels:

  1. - "traefik.tcp.routers.mongo1.rule=HostSNI(`mongo1.local`)"
  2. - "traefik.tcp.routers.mongo1.tls=true"
  3. - "traefik.tcp.routers.mongo1.entrypoints=mongo"

mongo2: image: mongo:4.0 hostname: mongo2.local restart: always labels:

  1. - "traefik.tcp.routers.mongo2.rule=HostSNI(`mongo2.local`)"
  2. - "traefik.tcp.routers.mongo2.tls.passthrough=true"
  3. - "traefik.tcp.routers.mongo2.entrypoints=mongo"
  4. command:
  5. - "mongod"
  6. - "--sslMode=requireSSL"
  7. - "--sslPEMKeyFile=/etc/ssl/mongo.pem"
  8. volumes:
  9. - ./ssl:/etc/ssl

mongo-express: image: mongo-express:0.49 restart: always labels:

  1. - "traefik.http.routers.mongo-express.rule=Host(`dashboard-mongo1.local`)"
  2. - "traefik.http.routers.mongo-express.tls=true"
  3. - "traefik.http.routers.mongo-express.entrypoints=mongo"
  4. environment:
  5. ME_CONFIG_MONGODB_SERVER: mongo1
  1. traefik-tls.toml

[[tls.certificates]] certFile = “/etc/ssl/cert.pem” keyFile = “/etc/ssl/key.pem”

  1. 生成证书:

cd ssl rm -rf .pem sh generate-certificates.sh “mongo1.local,mongo2.local,dashboard-mongo1.local” ./ mv certs/ .

  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mongo1.local mongo2.local dashboard-mongo1.local

  1. 使用mongo客户端连接:

Mongo 1

mongo —host mongo1.local —port 27017 —ssl —sslCAFile=./ssl/minica.pem —sslPEMKeyFile=./ssl/mongo.pem

show dbs use meetup db.movie.insert({“name”:”Traefik-Awesome”}) db.movie.find() show dbs exit

Mongo2

mongo —host mongo2.local —port 27017 —ssl —sslCAFile=./ssl/minica.pem —sslPEMKeyFile=./ssl/mongo.pem

show dbs exit

  1. 浏览器访问 [https://dashboard-mongo1.local:27017/](https://dashboard-mongo1.local:27017/) ,检查 meetup 数据库是否存在。<br />![image-20191225193401174](https://tva1.sinaimg.cn/large/006tNbRwly1ga9763dk72j31vu0pkq7a.jpg)<br />证书不受信任,需要将 minica.pem ROOT CA证书加到浏览器。<br />清理:

docker-compose down -v

  1. 5、使用ACME生成证书<br />docker-compose.yml

version: ‘3’

services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --providers.file.filename=/etc/ssl/traefik-tls.toml
  5. - --entrypoints.mongo.address=:27017
  6. - --certificatesResolvers.sample.acme.dnsChallenge.provider=dnspod
  7. - --certificatesResolvers.sample.acme.email=chenzj@wesine.com
  8. - --certificatesResolvers.sample.acme.storage=/etc/traefik/acme.json
  9. - --certificatesResolvers.sample.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
  10. ports:
  11. - "27017:27017"
  12. - "8080:8080"
  13. volumes:
  14. - /var/run/docker.sock:/var/run/docker.sock
  15. - ../ssl:/etc/ssl

mongo1: image: mongo:4.0 hostname: mongo1.local restart: always labels:

  1. - traefik.tcp.routers.mongo1.rule=HostSNI(`mongo1.local`)
  2. - traefik.tcp.routers.mongo1.entrypoints=http
  3. - traefik.http.routers.mongo1-https.rule=HostSNI(`mongo1.local`)
  4. - traefik.http.routers.mongo1-https.entrypoints=https
  5. - traefik.http.routers.mongo1-https.tls=true
  6. - traefik.http.routers.mongo1-https.tls.certresolver=sample
  7. # http 重定向到 https
  8. - traefik.http.routers.mongo1.middlewares=redirect-http
  9. - traefik.http.middlewares.redirect-http.redirectscheme.scheme=https
  10. - traefik.http.middlewares.redirect-http.redirectscheme.port=443
  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mongo1.local mongo2.local dashboard-mongo1.local

  1. 使用mongo客户端连接:

Mongo 1

mongo —host mongo1.local —port 443 —ssl

show dbs use meetup db.movie.insert({“name”:”Traefik-Awesome”}) db.movie.find() show dbs exit

  1. ## 测试Mysql TCP路由
  2. 1、测试简单TCP路由<br />docker-compose.yml

version: ‘3’ services: reverse-proxy: image: traefik:latest command:

  1. - --api
  2. - --api.insecure
  3. - --providers.docker
  4. - --entrypoints.mysql.address=:3306
  5. ports:
  6. - "3306:3306"
  7. - "8080:8080"
  8. volumes:
  9. - /var/run/docker.sock:/var/run/docker.sock

mysql: image: mysql:5.7 labels:

  1. - "traefik.tcp.routers.mysql.rule=HostSNI(`*`)"
  2. - "traefik.tcp.routers.mysql.entrypoints=mysql"
  3. command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  4. environment:
  5. MYSQL_ROOT_PASSWORD: 123456
  6. MYSQL_DATABASE: gogs
  7. MYSQL_USER: gogs
  8. MYSQL_PASSWORD: 123456
  9. TZ: Asia/Shanghai
  1. 启动:

docker-compose up -d

  1. 设置/etc/hosts:

127.0.0.1 mysql.local

  1. 使用mongo客户端连接:

mysql -h 127.0.0.1 -uroot -P3306 -p

show databases; exit

  1. 清理:

docker-compose down -v

```

参考文章