首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在同一个主机上侦听相同的2个端口的码头容器

在同一个主机上侦听相同的2个端口的码头容器
EN

Stack Overflow用户
提问于 2022-06-07 10:38:14
回答 1查看 379关注 0票数 -1

我正在尝试使不同的Python脚本运行在不同的容器上,配置为docker,能够侦听相同的端口。每个容器( 9)都应该监听端口1883和8086。这样做的目的是编写一个坞-撰写文件,其中每个服务都具有以下特征:

代码语言:javascript
运行
复制
  sensor1:
    build: ./sensor1
    image: sensor1:latest
    ports:
     - "8086:80"
     - "1883:80"
....
....
  sensor9:
    build: ./sensor9
    image: sensor9:latest
    ports:
     - "8086:80"
     - "1883:80"

我知道,对于普通的码头组合文件,它不工作,我需要一个反向代理,但我被困在这个反向代理(即Traefik)配置。实际上,这些脚本应该侦听从外部代理接收的端口1883,并在位于同一主机上的数据库上写入,该数据库可以使用端口8086进行访问。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-07 12:07:50

绑定到多个地址

当侦听同一个主机地址时,不能将多个容器的端口绑定到同一个主机端口。做这样的配置的唯一方法是将端口绑定到主机上的不同地址。例如,如果我的主机上有多个与eth0相关的地址:

代码语言:javascript
运行
复制
$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.1.175/24 brd 192.168.1.255 scope global dynamic noprefixroute eth0
       valid_lft 49625sec preferred_lft 49625sec
    inet 192.168.1.200/24 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.201/24 scope global secondary eth0
       valid_lft forever preferred_lft forever

然后,我可以将每个容器绑定到特定的地址,如下所示:

代码语言:javascript
运行
复制
  sensor1:
    build: ./sensor1
    image: sensor1:latest
    ports:
     - "192.168.1.175:8086:80"
     - "192.168.1.175:1883:80"
[...]
  sensor2:
    build: ./sensor2
    image: sensor2:latest
    ports:
     - "192.168.1.200:8086:80"
     - "192.168.1.200:1883:80"
[...]

然后,到http://192.168.1.175:8086的连接将转到sensor1容器,而到http://192.168.1.200:8086的连接将转到sensor2容器。

基于主机名和路径的路由

如果您希望将所有内容都托管在同一个地址,那么您需要另一种策略来区分容器。你的选择是有效的:

  • hostname --将多个主机名配置为指向同一个ip地址,像特雷菲克这样的负载均衡器将使用主机名将传入连接定向到适当的容器。
  • path --每个容器都在不同的路径上公开(例如,http://myhost/sensor1到sensor1,http://myhost/sensor2到sensor2,等等)。负载平衡器使用传入请求中包含的路径来路由通信量。

路径示例

我将从路径示例开始,因为这通常是最简单的。它不需要在多台机器上设置DNS条目或使用/etc/hosts

以下docker-compose.yaml演示了基于路径的路由配置:

代码语言:javascript
运行
复制
version: '3'

services:

  # This is the load balancer. To match the configuration you show in
  # your question, I have it listening on ports 8086 and 1883 in
  # addition to port 80.
  #
  # The default configuration of Traefik is to expose a management
  # interface on port 8080; if you don't want that, you can remove
  # the corresponding `ports` entry.
  reverse-proxy:
    image: traefik:v2.7
    command: --api.insecure=true --providers.docker
    ports:
      - "80:80"
      - "8086:80"
      - "1883:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  # In our container configuration, we use labels to configure
  # Traefik. Here, we're declaring that requests prefixed by `/sensor1`
  # will be routed to this container, and then we strip the `/sensor1`
  # prefix from the request (so that the service running inside the
  # container doesn't see the prefix).
  #
  # Note that we're not publishing any ports here: only the load
  # balancer has ports published on the host.
  sensor1:
    hostname: sensor1
    labels:
      - traefik.enable=true
      - traefik.http.routers.sensor1.rule=PathPrefix(`/sensor1`)
      - traefik.http.services.sensor1.loadbalancer.server.port=80
      - traefik.http.middlewares.strip-sensor1.stripprefix.prefixes=/sensor1
      - traefik.http.routers.sensor1.middlewares=strip-sensor1
    build: ./sensor1

  sensor2:
    hostname: sensor2
    labels:
      - traefik.enable=true
      - traefik.http.routers.sensor2.rule=PathPrefix(`/sensor2`)
      - traefik.http.services.sensor2.loadbalancer.server.port=80
      - traefik.http.middlewares.strip-sensor2.stripprefix.prefixes=/sensor2
      - traefik.http.routers.sensor2.middlewares=strip-sensor2
    build: ./sensor2

如果每个容器都运行一个在/hostname.txt中包含主机名的服务,我将看到以下行为:

代码语言:javascript
运行
复制
$ curl myhost/sensor1/hostname.txt
sensor1
$ curl myhost/sensor2/hostname.txt
sensor2

主机名示例

基于主机的配置看起来基本相同,但rule使用的是Host匹配而不是PathPrefix匹配(我们不再需要前缀剥离逻辑):

代码语言:javascript
运行
复制
version: '3'

services:
  reverse-proxy:
    image: traefik:v2.7
    command: --api.insecure=true --providers.docker
    ports:
      - "80:80"
      - "8086:80"
      - "1883:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  sensor1:
    hostname: sensor1
    labels:
      - traefik.enable=true
      - traefik.http.routers.sensor1.rule=Host(`sensor1`)
      - traefik.http.services.sensor1.loadbalancer.server.port=8080
    build:
      context: web

  sensor2:
    hostname: sensor2
    labels:
      - traefik.enable=true
      - traefik.http.routers.sensor2.rule=Host(`sensor2`)
      - traefik.http.services.sensor2.loadbalancer.server.port=8080
    build:
      context: web

  sensor3:
    hostname: sensor3
    labels:
      - traefik.enable=true
      - traefik.http.routers.sensor3.rule=Host(`sensor3`)
      - traefik.http.services.sensor3.loadbalancer.server.port=8080
    build:
      context: web

为此,需要将多个主机名映射到docker主机。您可以通过设置适当的DNS条目,或者在任何需要联系这些服务的机器上向/etc/hosts添加适当的条目来实现这一点。

我们可以通过在请求中设置显式Host头来演示配置:

代码语言:javascript
运行
复制
$ curl -H 'Host: sensor1' myhost/hostname.txt
sensor1
$ curl -H 'Host: sensor2' myhost/hostname.txt
sensor2
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72529750

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档