使用Docker和Traefik反向代理微服务

时间:2018-06-15 11:28:01

标签: docker docker-compose traefik

我的微服务很少,我们称它为food-msreceipt-msingredients-msfrontend,而React App会消耗这些微服务。 他们每个人都在/api/[methods]公开API。

我想使用Docker和docker-compose为下一个属性创建生产和开发环境:

  • 应该可以在单个主机上使用应用程序。在生产中,主机应该是例如http://food-app.test,对于开发它应该(理想情况下)localhost

  • 每个微服务和前端应该在单个主机上,但是在不同的路径上。例如,food-ms API应位于localhost/food/apireceipt-ms API应位于localhost/receipt/api等。前端应位于localhost root /路径。

  • 理想情况下,我希望能够在外部容器中运行一些服务以便于调试,但仍然可以通过localhost/{service}/api进行反向代理并提供。

    < / LI>

我找到了一个traefik反向代理,并对其进行了一些实验,但遇到了问题:

  1. 如何在某些可预测的域中提供应用,例如localhost。目前,我可以通过在Host标头中指定一个奇怪的主机来代理对特定后端的请求,例如<container-name>.<network-name>.docker.localhost 似乎traefik.toml中描述的前端没有效果。
  2. 如何根据路径将请求从一个前端路由到不同的后端?
  3. 如何将请求路由到外部IP和端口(我想用它来运行容器外的服务进行调试)?我应该在docker中使用host网络吗?
  4. 提前致谢。

    这是我的traefik.toml

    defaultEntryPoints = ["http"]
    
    [entryPoints]
        [entryPoints.http]
        address = ":80"
    
    [file]
    
    [frontends]
        [frontends.food]
        entrypoints = ["http"]
        backend="food"
    
        [frontends.receipts]
        entrypoints = ["http"]
        backend="receipts"
    

    这些前端似乎没有得到应用,因​​为如果我推荐它们,仪表板不会改变。

3 个答案:

答案 0 :(得分:1)

花了一些时间后,我的问题取得了一些成功。

首先,尝试使用本地应用程序而非docker容器运行traefik要容易得多。

所以我在本地安装了traefik(brew install traefik)并使用下一个命令行运行它:

traefik --web --configfile=./docker/traefik-local.toml --logLevel=INFO

有一个弃用但有效的参数--web,同时可以省略。

然后我创建了一个带配置

的TOML文件
defaultEntryPoints = ["http"]
[entryPoints]
    [entryPoints.http]
    address = ":80"

[file]

[frontends]
    [frontends.fin]
        entrypoints = ["http"]
        backend="fin"
        [frontends.fin.routes.matchUrl]
            rule="PathPrefixStrip:/api/fin"
        [frontends.fin.routes.rewriteUrl]
            rule = "AddPrefix: /api"

    [frontends.proj]
    entrypoints = ["http"]
    backend="proj"
        [frontends.proj.routes.matchUrl]
            rule="PathPrefixStrip: /api/proj"
        [frontends.proj.routes.rewriteUrl]
            rule = "AddPrefix: /api"


[backends]
    [backends.fin]
        #
        [backends.fin.servers.main]
        url = "http://localhost:81"
    [backends.proj]
        #
        [backends.proj.servers.main]
        url = "http://localhost:82"

服务名称与初始答案不同,但想法应该清楚。

首先,在描述前端和后端之前,有强制[file]指令。没有它,它没有用,arghh :(

服务在docker容器中运行,并为fin公开端口81,为proj公开82。从现在开始,traefik在docker isolated网络之外工作,它支持在容器中本机运行应用程序和应用程序。

然后描述了两个前端。最初我还遇到了规则问题:PathPrefixStrip Matcher ,但它也通过删除路径前缀来修改路径。

所以现在它可以按照我想要的本地运行方式运行,并且它应该更容易让它在Docker中运行。

答案 1 :(得分:0)

好吧,关于在Docker中运行所有内容的更多信息。

首先,traefik有一个配置提供的概念,它可以获得有关后端,前端,规则,映射等的所有信息。

对于Docker,至少有两种方法:在docker-compose.yml中使用服务标签或使用file配置提供程序。

这里我会考虑使用文件配置提供程序。 要使用它,您需要将以下[file]部分和配置添加到traefik配置或使用分隔文件。

我使用了分隔文件,启用并通过添加--file --file.filename=/etc/traefik/traefik.file.toml命令行参数来指向它。

请记住,如果你使用Windows和docker-toolbox,你需要在Virtual Box中添加共享文件夹并添加相对于该文件夹的映射,这很痛苦,是的。

之后,其他事情很容易。

要解决traefik配置的[backends]部分中的服务,请使用docker-compose.yml中的服务名称。公开代理使用端口映射。

这是我的docker-compose.yaml

version: "3"
services:     

  financial-service:
    build:
      context: .
      dockerfile: ./docker/financial.Dockerfile

  project-service:
    build:
      context: .
      dockerfile: ./docker/project.Dockerfile

  traefik:
    image: traefik
    command: --web --docker --file --file.filename=/etc/traefik/traefik.file.toml --docker.domain=docker.localhost --logLevel=INFO --configFile=/etc/traefik/traefik.toml
    ports:
      - "80:80"
      - "8088:8080"
      # - "44:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # On Windows with docker-toolbox:
      #    this should be mounted as a shared folder in VirtualBox.
      # Mount via VB UI, don't forget to restart docker machine.

      # - /rd-erp/docker:/etc/traefik/
      # On normal OS
      - ./docker:/etc/traefik/
    depends_on:
      - project-service
      - financial-service

以下是Docker的traefik.file.toml

[frontends]
    [frontends.fin]
        entrypoints = ["http"]
        backend="fin"
        [frontends.fin.routes.matchUrl]
            rule="PathPrefixStrip:/api/fin"
        [frontends.fin.routes.rewriteUrl]
            rule = "AddPrefix: /api"

    [frontends.proj]
    entrypoints = ["http"]
    backend="proj"
        [frontends.proj.routes.matchUrl]
            rule="PathPrefixStrip: /api/proj"
        [frontends.proj.routes.rewriteUrl]
            rule = "AddPrefix: /api"


[backends]
    [backends.fin]
        #
        [backends.fin.servers.main]
        url = "http://financial-service"
    [backends.proj]
        #
        [backends.proj.servers.main]
        url = "http://project-service"

下一步是在容器外运行一些服务,并且仍然能够从localhost反向代理它。

答案 2 :(得分:0)

And probably the last part: connecting to the services running on the host machine from the Docker, and in our case, from the traefik container.

  1. Run service on the host machine
  2. In Docker 18.3+ use special domain host.docker.internal and don't forget to specify protocol and port.

    In earlier Docker probably would need to use host network mode. This would involve extra configuration of services to don't overlap with busy ports, but probably wouldn't require changing configuration for running services outside container.

  3. Run docker-compose without service you would like to debug:

    docker-compose up --no-deps traefik financial-service

  4. Enjoy

Don't forget to remove [file] section from traefik.toml if you use configuration in separated file provided by --file.filename, seems [file] section takes precedences.