跳转至

Docker

标签和容器的故事

Docker

将标签添加到你的容器之上,让 Traefik 来完成其余的工作!

快速入门使用 Docker

如果你还没使用 Docker Provider 的话,可以通过这个 快速开始 的示例来了解 Docker Provider!

配置示例

配置 Docker 和部署/暴露服务

开启 docker provider

[providers.docker]
providers:
  docker: {}
--providers.docker=true

添加 label 标签到容器上 (在 docker compose 文件中)

version: "3"
services:
  my-container:
    # ...
    labels:
      - traefik.http.routers.my-container.rule=Host(`mydomain.com`)

移除 Docker Swarm 文档

由于现阶段 Docker Swarm 的使用不是很多,所以移除 Swarm 的相关文档介绍,重点放在 Docker 和 Kubernetes 上面,有需要的可以千万官方文档查看 Swarm 相关配置。

路由配置

查看特定的 路由文档 部分了解更多信息。

Provider 配置

endpoint

必填, 默认值:"unix:///var/run/docker.sock"

[providers.docker]
  endpoint = "unix:///var/run/docker.sock"
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
--providers.docker.endpoint="unix:///var/run/docker.sock"

Traefik 需要访问 Docker 套接字来获取其动态配置。

安全须知

根据你的上下文,对 Docker API 进行无限制的访问可能是一个安全问题:如果 Traefik 受到攻击,则攻击者可能会访问到 Docker 后端程序。更多信息可以查看 Docker 官方文档 关于 Docker Daemon 的攻击信息:

[...] 只有 **被信任的** 用户才允许访问控制你的 Docker Daemon [...]

有关 Docker 安全性的资源
安全补偿

通过 TCP 来暴露 Docker socket,而不是使用默认的 Unix socket 文件。

根据你的安全评估,它允许 AAA (Authentication, Authorization, Accounting) 概念 的不同实现级别:

AAA 提供的安全服务具体是指
  • 认证(Authentication):是对用户的身份进行验证,判断其是否为合法用户。
  • 授权(Authorization):是对通过认证的用户,授权其可以使用哪些服务。
  • 计费(Accounting):是记录用户使用网络服务的资源情况,这些信息将作为计费的依据。
  • 使用客户端证书进行身份认证:"保护 Docker Daemon Socket"
  • 使用 Docker 授权插件机制 进行授权
  • 在网络级别进行计费,只在 Docker 私有网络中暴露套接字文件,仅对 Traefik 可用。
  • 在容器级别进行计费,通过将套接字暴露在 Traefik 以外的另一个容器上。
  • 在内核级别进行计费,通过使用 SELinux 之类的机制强制执行内核调用,从而仅允许为 Traefik 的进程指定一组确定的操作。
其他资源
使用 docker.sock

docker-compose 文件和 Traefik 容器共享 docker sock 文件

version: '3'

services:
  traefik:
     image: traefik:v2.0 # The official v2.0 Traefik docker image
     ports:
       - "80:80"
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock

在 Traefik 的配置文件中指定 docker.sock。

[providers.docker]
  endpoint = "unix:///var/run/docker.sock"
  # ...
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
     # ...
--providers.docker.endpoint="unix:///var/run/docker.sock"
# ...

useBindPortIP

可选, 默认值为 false

[providers.docker]
  useBindPortIP = true
  # ...
providers:
  docker:
    useBindPortIP: true
    # ...
--providers.docker.useBindPortIP=true
# ...

Traefik 将请求路由到匹配容器的 IP/Port。当设置 useBindPortIP=true 时,Traefik 使用连接到容器的 binding 的 IP/Port,而不是其内部网络的 IP/Port。

当与 traefik.http.services.<name>.loadbalancer.server.port 标签结合使用(告诉 Traefik 将请求路由到特定端口)时,Traefik 尝试在端口 traefik.http.services.<name>.loadbalancer.server.port 上找到绑定。

如果这不到这样的绑定,Traefik 将退回到容器的内部网络 IP 上,但仍使用标签中设置的 traefik.http.services.<name>.loadbalancer.server.port

不同情形下的 usebindportip 示例
端口标签 容器的绑定 路由目标
- - IntIP:IntPort
- ExtPort:IntPort IntIP:IntPort
- ExtIp:ExtPort:IntPort ExtIp:ExtPort
LblPort - IntIp:LblPort
LblPort ExtIp:ExtPort:LblPort ExtIp:ExtPort
LblPort ExtIp:ExtPort:OtherPort IntIp:LblPort
LblPort ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 ExtIp2:LblPort

在上表中:

  • ExtIp 表示 "绑定中找到的外部 IP"
  • IntIp 表示 "内部网络容器的 IP"
  • ExtPort 表示 "绑定中找到的外部端口"
  • IntPort 表示 "内部网络容器的端口"

exposedByDefault

可选, 默认为 true

[providers.docker]
  exposedByDefault = false
  # ...
providers:
  docker:
    exposedByDefault: false
    # ...
--providers.docker.exposedByDefault=false
# ...

默认情况下通过 Traefik 暴露容器。如果设置为 false,没有 traefik.enable=true 标签的容器则会被最终的路由配置所忽略。

也可以查看 限制服务发现范围 文档了解更多信息。

network

可选, 默认为 empty

[providers.docker]
  network = "test"
  # ...
providers:
  docker:
    network: test
    # ...
--providers.docker.network=test
# ...

定义用于连接所有容器的默认 docker 网络。也可以使用容器标签 traefik.docker.network 来覆盖该选项。

defaultRule

可选, 默认值为 Host(`{{ normalize .Name }}`)

[providers.docker]
  defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
  # ...
providers:
  docker:
    defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
    # ...
--providers.docker.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...

对于一个特定的容器,如果标签没有定义任何路由规则,则由 defaultRule 来代替。该值必须是一个有效的 Go 模板,另外还包括一些 sprig 模板函数

容器服务名称可以作为 Name 标识来访问,并且模板可以访问该容器上定义的所有标签。

constraints

可选, 默认为空 ""

[providers.docker]
  constraints = "Label(`a.label.name`, `foo`)"
  # ...
providers:
  docker:
    constraints: "Label(`a.label.name`, `foo`)"
    # ...
--providers.docker.constraints="Label(`a.label.name`, `foo`)"
# ...

约束是 Traefik 和容器标签匹配的一个表达式,用来确定是否为该容器创建路由信息。也就是说,如果容器的标签不匹配表达式的话,就不会创建容器的路由。如果表达式为空,则包括所有检测到的容器(也就是不过滤)。

表达式语法基于 Label("key", "value")LabelRegex("key", "value") 函数以及通常的布尔逻辑,如下所示:

约束表达式示例
# 包含 key 为 `a.label.name` value 为 `foo` 的标签的容器
constraints = "Label(`a.label.name`, `foo`)"
# 包含 key 为 `a.label.name` value 为 `foo` 的标签的容器
constraints = "!Label(`a.label.name`, `value`)"
# 逻辑 `与` 操作 
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
# 逻辑 `或` 操作 
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
# 使用逻辑 `与` 和 `或` 操作,通过括号设置优先级。
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
# 包括 key 为 `a.label.name` value 匹配 `a.+` 正则表达式的值的容器
constraints = "LabelRegex(`a.label.name`, `a.+`)"

同样也可以查看 限制服务发现范围 文档了解更多信息。

tls

可选

tls.ca

用于安全连接 Docker 的 CA 证书。

[providers.docker.tls]
  ca = "path/to/ca.crt"
providers:
  docker:
    tls:
      ca: path/to/ca.crt
--providers.docker.tls.ca=path/to/ca.crt

tls.caOptional

遵循与 TLS 客户端身份验证到 Docker 的安全连接策略。需要定义 tls.ca

  • true: VerifyClientCertIfGiven
  • false: RequireAndVerifyClientCert
  • 如果 tls.ca 未定义 NoClientCert
[providers.docker.tls]
  caOptional = true
providers:
  docker:
    tls:
      caOptional: true
--providers.docker.tls.caOptional=true

tls.cert

用于安全连接到 Docker 的公钥证书。

[providers.docker.tls]
  cert = "path/to/foo.cert"
  key = "path/to/foo.key"
providers:
  docker:
    tls:
      cert: path/to/foo.cert
      key: path/to/foo.key
--providers.docker.tls.cert=path/to/foo.cert
--providers.docker.tls.key=path/to/foo.key

tls.key

用于安全连接到 Docker 的私钥证书。

[providers.docker.tls]
  cert = "path/to/foo.cert"
  key = "path/to/foo.key"
providers:
  docker:
    tls:
      cert: path/to/foo.cert
      key: path/to/foo.key
--providers.docker.tls.cert=path/to/foo.cert
--providers.docker.tls.key=path/to/foo.key

tls.insecureSkipVerify

如果 insecureSkipVerify 设置为 true,则与 Docker 连接的 TLS 可以接收服务器提供的任何证书和证书中的任何主机名。

[providers.docker.tls]
  insecureSkipVerify = true
providers:
  docker:
    tls:
      insecureSkipVerify: true
--providers.docker.tls.insecureSkipVerify=true