Traefik 路由到 Docker 容器
创建一个新的 docker 网络
docker network create traefik_net
Traefik 和 containers(容器)需要在同一网络上。Compose 会自动创建一个,但事实是隐藏的,以后可能会发生混乱。最好仅创建自己的网络并将其设置为每个 compose 文件中的默认网络。
使用 docker network inspect traefik_net
查看连接到该网络的容器
创建 traefik.yml
该文件包含所谓的静态 traefik 配置。
在此基本示例中,只有很少的关于 settings(设置)的解释。
因为 exposedbydefault 被设置为 false,标签 "traefik.enable=true"
将需要用于应该由 traefik 路由的容器。
这个文件将通过 bind mount 传递给 docker 容器,这将在我们为 traefik 使用 docker-compose.yml 时完成。
traefik.yml
## STATIC CONFIGURATION log: level: INFO api: insecure: true dashboard: true entryPoints: web: address: ":80" providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false
稍后,当 traefik 容器运行时,使用命令 docker logs traefik
, 检查是否有提示:"Configuration loaded from file: /traefik.yml"
。您不想成为对 traefik.yml 进行更改的 moron
,并且它什么也不做,因为实际上并未使用该文件。
创建 .env
它包含一些环境变量。
域名,API密钥,IP地址,密码…… 无论是针对一种情况的特定情况,还是针对另一种情况的不同情况,所有这些都理想地放在了这里。运行 docker-compose up
命令时,这些变量可用于 docker-compose。
这使得编写文件可以更自由地从一个系统移动到另一个系统,并且可以对 .env
文件进行更改, 因此,在大型编写文件或类似文件中忘记更改某些主机规则中的域名的错误可能性更小。
.env
MY_DOMAIN=example.com DEFAULT_NETWORK=traefik_net
命令 docker-compose config
显示了填充变量后的 compose 状态。
这些变量仅在容器的初始构建期间填写。如果一个 env 变量也应该在运行的容器中可用,则需要在 compose 文件的 environment
部分声明它。
创建 traefik-docker-compose.yml
这是一个简单的典型 compose 文件。
端口 80 已映射,因为我们希望 traefik 负责端口上的内容-将其用作 entrypoint(入口点)。端口 8080 用于 traefik 显示信息的仪表板。需要挂载 docker.sock,因此它实际上可以完成与 docker 交互的工作。 traefik.yml
的挂载是给出静态 traefik 配置的原因。默认网络被设置为第一步中创建的网络,因为它将在所有其他 compose 文件中设置。
traefik-docker-compose.yml
version: "3.7" services: traefik: image: "traefik:v2.1" container_name: "traefik" hostname: "traefik" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./traefik.yml:/traefik.yml:ro" networks: default: external: name: $DEFAULT_NETWORK
运行 traefik-docker-compose.yml
docker-compose -f traefik-docker-compose.yml up -d
将会启动 traefik 容器。
traefik 正在运行,您可以在 ip:8080 上检查它,在那里您可以得到仪表板。
也可以用 docker logs traefik
检查日志。
通常你会看到指南只有一个名为 docker-compose.yml
文件。其中包含多个服务/容器。然后只需 docker-compose up -d
就可以开始了。当所有都是一个 compose 时,你甚至不需要费心去定义网络。但这一次,我更喜欢在学习新东西时采取小而独立的步骤。这就是为什么使用自定义命名的 docker-compose 文件,因为它允许更容易的分离。
您在教程中还可以看到没有提及 traefik.yml,而东西只是使用 traefik 的命令或标签从 docker-compose 传递的。
如: command: --api.insecure=true --providers.docker
但是这样一来,组合文件看起来会更加混乱,您仍然无法从那里进行任何操作,有时您仍然需要 traefik.yml。
所以...现在,使用结构良好的可读 traefik.yml
在 traefik 应该路由的容器上添加标签
以下是 whoami,nginx,apache,portainer 的示例。
- "traefik.enable=true"
启用 traefik
- "traefik.http.routers.whoami.entrypoints=web"
定义名为 whoami
的路由,该路由在入口点 Web(端口80)上侦听
- "traefik.http.routers.whoami.rule=Host(
whoami.$MY_DOMAIN
)"
定义此 whoami
路由规则,特别是当 url 等于 whoami.example.com
(域名来自 .env
文件)时, 这意味着路由可以完成其工作并将其路由到服务。
不需要其他任何东西,traefik 可以从这些标签来自 docker 容器的上下文中了解其余信息。
whoami-docker-compose.yml
version: "3.7" services: whoami: image: "containous/whoami" container_name: "whoami" hostname: "whoami" labels: - "traefik.enable=true" - "traefik.http.routers.whoami.entrypoints=web" - "traefik.http.routers.whoami.rule=Host(`whoami.$MY_DOMAIN`)" networks: default: external: name: $DEFAULT_NETWORK
nginx-docker-compose.yml
version: "3.7" services: nginx: image: nginx:latest container_name: nginx hostname: nginx labels: - "traefik.enable=true" - "traefik.http.routers.nginx.entrypoints=web" - "traefik.http.routers.nginx.rule=Host(`nginx.$MY_DOMAIN`)" networks: default: external: name: $DEFAULT_NETWORK
apache-docker-compose.yml
version: "3.7" services: apache: image: httpd:latest container_name: apache hostname: apache labels: - "traefik.enable=true" - "traefik.http.routers.apache.entrypoints=web" - "traefik.http.routers.apache.rule=Host(`apache.$MY_DOMAIN`)" networks: default: external: name: $DEFAULT_NETWORK
portainer-docker-compose.yml
version: "3.7" services: portainer: image: portainer/portainer container_name: portainer hostname: portainer volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - portainer_data:/data labels: - "traefik.enable=true" - "traefik.http.routers.portainer.entrypoints=web" - "traefik.http.routers.portainer.rule=Host(`portainer.$MY_DOMAIN`)" networks: default: external: name: $DEFAULT_NETWORK volumes: portainer_data:
运行容器
docker-compose -f whoami-docker-compose.yml up -d docker-compose -f nginx-docker-compose.yml up -d docker-compose -f apache-docker-compose.yml up -d docker-compose -f portainer-docker-compose.yml up -d
停止所有容器运行:docker stop $(docker ps -q)
Traefik 路由到本地 IP 地址
当 url 应该瞄准其他东西而不是 docker 容器。
定义 file provider,添加所需的路由和服务
所需要的是一个能够捕获某些 url 并将其路由到某些 IP 的 router。前面的示例显示了如何在端口 80 上捕获任何 url,但是没有人告诉它在符合规则的情况下该怎么做。Traefik 只是知道,因为它是在容器的上下文中使用标签完成的, 而且由于 docker 在 traefik.yml
中被设置为提供程序。
对于这种 “在某些 IP 上发送流量”,需要 traefik 服务, 并且要定义 traefik 服务,需要一个新的提供程序, 即 file provider - 只是一个(fucking stupid)文件,告诉 traefik 该怎么做。
某种常见的做法是将 traefik.yml
本身设置为 file provider,以便进行处理。
在提供者下有一个新的 file
部分,并设置了 traefik.yml
本身。
然后添加动态配置的东西。
一个名为 route-to-local-ip
的 router,有一个简单的子域主机名规则。符合该规则(在本例中为确切的网址 test.example.com
)的内容将发送到 loadbalancer 服务, 该服务会将其路由到特定的 IP 和特定的端口。
traefik.yml
## STATIC CONFIGURATION log: level: INFO api: insecure: true dashboard: true entryPoints: web: address: ":80" providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false file: filename: "traefik.yml" ## DYNAMIC CONFIGURATION http: routers: route-to-local-ip: rule: "Host(`test.example.com`)" service: route-to-local-ip-service priority: 1000 entryPoints: - web services: route-to-local-ip-service: loadBalancer: servers: - url: "http://10.0.19.5:80"
路由的优先级设置为 1000,这是一个非常高的值,超过了任何其他可能的路由。
不幸的是 .env
变量在这里不起作用,否则主机规则中的域名和 IP 将来自变量。因此,抬起头来,您肯定会忘记更改这些。
运行 traefik-docker-compose
测试是否有效
docker-compose -f traefik-docker-compose.yml up -d
Traefik 中间件
任何容器的身份验证中间件的示例。
创建一个新文件 users_credentials
包含 username:passwords 对,htpasswd 格式
在下面的示例中,密码 krakatoa
设置为下面所有3个帐户
users_credentials
me:$apr1$L0RIz/oA$Fr7c.2.6R1JXIhCiUI1JF0 admin:$apr1$ELgBQZx3$BFx7a9RIxh1Z0kiJG0juE/ bastard:$apr1$gvhkVK.x$5rxoW.wkw1inm9ZIfB0zs1
挂载 users_credentials
traefik-docker-compose.yml
version: "3.7" services: traefik: image: "traefik:v2.1" container_name: "traefik" hostname: "traefik" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./traefik.yml:/traefik.yml:ro" - "./users_credentials:/users_credentials:ro" networks: default: external: name: $DEFAULT_NETWORK
在应该进行身份验证的任何容器中添加两个标签
- 第一个标签将名为
auth-middleware
的新中间件附加到已存在的whoami
路由器上。 - 第二个标签为该中间件提供了 basicauth 类型,并告诉它用于认证用户的文件在哪里。
无需在此处安装 users_credentials
,它是 traefik 所需的文件, 这些标签是一种将信息传递给 traefik 的方式,它应该在容器的上下文中进行操作。
whoami-docker-compose.yml
version: "3.7" services: whoami: image: "containous/whoami" container_name: "whoami" hostname: "whoami" labels: - "traefik.enable=true" - "traefik.http.routers.whoami.entrypoints=web" - "traefik.http.routers.whoami.rule=Host(`whoami.$MY_DOMAIN`)" - "traefik.http.routers.whoami.middlewares=auth-middleware" - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=/users_credentials" networks: default: external: name: $DEFAULT_NETWORK
nginx-docker-compose.yml
version: "3.7" services: nginx: image: nginx:latest container_name: nginx hostname: nginx labels: - "traefik.enable=true" - "traefik.http.routers.nginx.entrypoints=web" - "traefik.http.routers.nginx.rule=Host(`nginx.$MY_DOMAIN`)" - "traefik.http.routers.nginx.middlewares=auth-middleware" - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=/users_credentials" networks: default: external: name: $DEFAULT_NETWORK
运行容器,现在需要登录名和密码
docker-compose -f traefik-docker-compose.yml up -d docker-compose -f whoami-docker-compose.yml up -d docker-compose -f nginx-docker-compose.yml up -d