如何使用 docker 管理暴露在端口 80 上的多个端口?

How to manage multiple ports exposed on port 80 with docker?

我有以下设置:

version: '3'

services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    ports:
      - 80:80
    command:
      - --api.debug=true
      - --api.insecure=true
      - --providers.docker=true
      - --entrypoints.web.address=:80
      - --providers.docker.exposedByDefault=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    labels:
      - traefik.http.routers.traefik.service=api@internal
      - traefik.http.routers.traefik.rule=Host(`monitor.domain.org`)
      - traefik.http.routers.traefik.entrypoints=web
    networks:
      - web
  db:
    image: registry.domain.com/repo/db:latest
    container_name: db
    restart: always
    networks:
      - internal
  api:
    image: registry.domain.com/repo/api:latest
    container_name: api
    ports:
      - 80:3001
    volumes:
      - /root/rsa.pem:/root/certs/rsa.pem
      - /root/rsa_pub.pem:/root/certs/rsa_pub.pem
    restart: always
    depends_on:
      - db
    environment:
      - MAIL_ADDRESS=${MAIL_ADDRESS}
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - MAIL_HOST=${MAIL_HOST}
    labels:
      - traefik.http.routers.api.rule=Host(`api.domain.org`)
      - traefik.http.routers.api.entrypoints=web
    networks:
      - internal
      - web
  app:
    image: registry.domain.com/repo/app:latest
    container_name: app
    restart: always
    depends_on:
      - api
      - db
    labels:
      - traefik.http.routers.app.rule=Host(`domain.org`,`www.domain.org`)
      - traefik.http.routers.app.entrypoints=web
    networks:
      - web

networks:
  web:
    external: true
  internal:
    external: false

显然我从 docker 那里得到一个错误说 Bind for 0.0.0.0:80 failed: port is already allocated。公开 traefik 服务的 port 80 或单独公开 api 服务都可以完美地工作。如果我不在这两种服务上公开 port 80,它对它们都不起作用。 Nginx 上 运行s 的 app 服务可以在不无缝暴露 port 80 的情况下工作。如何在 port 80 上同时提供 apitraefik 服务 运行?

实际上,您需要为 api 做您为应用程序所做的同样的事情,通过 traefik 公开它。

一般来说,您通常想要的是通过 traefik(或任何其他反向代理)公开所有集群内部服务,因此只有 traefik 应该公开主机的端口。您的所有其他服务都将注册到至少一个 entrypoint 的 traefik 以获得请求。

因此您只需从 api 服务中删除 ports: - 80:3001

将会发生的是 traefik 只会监听端口 80,并且所有具有 domain.orgwww.domain.org 的 http 主机 header 的 traefik 将被路由到应用程序服务所有带有 api.domain.org 的请求都将被路由到您的 api 服务。

如果您已完成上述操作但无法向您的 api 服务发送请求,请分享您服务中的一些日志以检查大多数情况下的错误,某些 header 需要传播后端服务,以便它们正常工作。

PS。您正在使用最新的 v2.0 版本的 traefik,显然将服务注册到入口点足以让 traefik 将请求路由到该服务。在以前的版本中,您应该向服务添加标签 traefik.port 以通告您的服务正在侦听的位置,这更明确地说明了正在发生的事情。 docs