Traefik 路由到一个 Docker 容器中的两个端口

Traefik 路由到一个 Docker 容器中的两个端口

我想从单个 Docker 容器提供两个 Web 服务器,并使用 Traefik 代理服务器通过两个端口公开它们。

我发现一个例子docker compose 文件,为两个 web 服务器提供服务两个独立的Docker容器:

version: "3"

services:

  # The `proxy` service set up two entrypoints (read that as
  # "listeners") for traefik, one on port 80 and one on port 9090.
  proxy:
    image: traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --entrypoints.ep1.address=:80
      - --entrypoints.ep2.address=:9090

    # We need to publish ports 80 and 9090. Here I'm also
    # publishing port 8080, which is the Traefik dashboard, but
    # that's not necessary.
    ports:
      - "80:80"
      - "8080:8080"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  # We bind container `app1` to entrypoint `ep1`, with a `Host`
  # rule matching `example.com`. I'm setting `...server.port` here
  # because the `darkhttpd` container listens on port 8080.
  app1:
    image: docker.io/alpinelinux/darkhttpd:latest
    volumes:
      - type: bind
        source: ./www80
        target: /var/www/localhost/htdocs
    labels:
      - traefik.enable=true
      - traefik.http.services.app1.loadbalancer.server.port=8080
      - traefik.http.routers.app1.rule=Host(`example.com`)
      - traefik.http.routers.app1.entrypoints=ep1

  # We bind container `app2` to entrypoint `ep2`, with a `Host`
  # rule matching `example.com`.
  app2:
    image: docker.io/alpinelinux/darkhttpd:latest
    volumes:
      - type: bind
        source: /home/don/Documents/docker-test/www9090
        target: /var/www/localhost/htdocs
    labels:
      - traefik.enable=true
      - traefik.http.services.app2.loadbalancer.server.port=8080
      - traefik.http.routers.app2.rule=Host(`example.com`)
      - traefik.http.routers.app2.entrypoints=ep2

我补充example.com/etc/hosts

127.0.0.1       example.com

当我请求http://example.com和时,这可以正常工作http://example.com:9090,但是我如何才能从单身的容器?

我尝试使用脚本从同一个容器启动两个服务器:

#!/usr/bin/env sh

darkhttpd /var/www/localhost/htdocs9090 --port 9090 &

darkhttpd /var/www/localhost/htdocs --port 8080

然后我合并两个容器定义:

version: "3"

services:

  # The `proxy` service set up two entrypoints (read that as
  # "listeners") for traefik, one on port 80 and one on port 9090.
  proxy:
    image: traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --entrypoints.ep1.address=:80
      - --entrypoints.ep2.address=:9090

    # We need to publish ports 80 and 9090. Here I'm also
    # publishing port 8080, which is the Traefik dashboard, but
    # that's not necessary.
    ports:
      - "80:80"
      - "8080:8080"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  # We bind container `app1` to both entrypoints `ep1` and `ep2`, with a `Host`
  # rule matching `example.com`. The launch script launches two darkhttpd
  # processes that listen on ports 8080 and 9090.
  app1:
    image: docker.io/alpinelinux/darkhttpd:latest
    volumes:
      - type: bind
        source: www80
        target: /var/www/localhost/htdocs
      - type: bind
        source: www9090
        target: /var/www/localhost/htdocs9090
      - type: bind
        source: launcher
        target: /var/www/localhost/launcher
    labels:
      - traefik.enable=true
      - traefik.http.services.app1.loadbalancer.server.port=8080
      - traefik.http.routers.app1.rule=Host(`example.com`)
      - traefik.http.routers.app1.entrypoints=ep1
      - traefik.http.services.app2.loadbalancer.server.port=9090
      - traefik.http.routers.app2.rule=Host(`example.com`)
      - traefik.http.routers.app2.entrypoints=ep2
    entrypoint: /var/www/localhost/launcher/launch.sh

当我运行时docker compose,它抱怨服务太多:

traefik-two-ports-proxy-1  | time="2023-12-22T23:35:03Z" level=error msg="Could not define the service name for the router: too many services" routerName=app2 providerName=docker

如何在不扰乱docker的情况下将服务合并到一个容器中?

答案1

经过一番搜索,我发现你需要明确名称当容器中有多个服务时。

version: "3"

services:

  # The `proxy` service set up two entrypoints (read that as
  # "listeners") for traefik, one on port 80 and one on port 9090.
  proxy:
    image: traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --entrypoints.ep1.address=:80
      - --entrypoints.ep2.address=:9090

    # We need to publish ports 80 and 9090. Here I'm also
    # publishing port 8080, which is the Traefik dashboard, but
    # that's not necessary.
    ports:
      - "80:80"
      - "8080:8080"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  # We bind container `app1` to both entrypoints `ep1` and `ep2`, with a `Host`
  # rule matching `example.com`. The launch script launches two darkhttpd
  # processes that listen on ports 8080 and 9090.
  # When a service container holds more than one service, you have to explicitly
  # name the service for each router.
  app1:
    image: docker.io/alpinelinux/darkhttpd:latest
    volumes:
      - type: bind
        source: www80
        target: /var/www/localhost/htdocs
      - type: bind
        source: www9090
        target: /var/www/localhost/htdocs9090
      - type: bind
        source: launcher
        target: /var/www/localhost/launcher
    labels:
      - traefik.enable=true
      - traefik.http.services.app1.loadbalancer.server.port=8080
      - traefik.http.routers.app1.service=app1
      - traefik.http.routers.app1.rule=Host(`example.com`)
      - traefik.http.routers.app1.entrypoints=ep1
      - traefik.http.services.app2.loadbalancer.server.port=9090
      - traefik.http.routers.app2.service=app2
      - traefik.http.routers.app2.rule=Host(`example.com`)
      - traefik.http.routers.app2.entrypoints=ep2
    entrypoint: /var/www/localhost/launcher/launch.sh

现在,我可以再次点击这两个按钮http://example.comhttp://example.com:9090同时只运行一个 Web 服务器容器。

相关内容