如何使用 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
上同时提供 api
和 traefik
服务 运行?
实际上,您需要为 api 做您为应用程序所做的同样的事情,通过 traefik 公开它。
一般来说,您通常想要的是通过 traefik(或任何其他反向代理)公开所有集群内部服务,因此只有 traefik 应该公开主机的端口。您的所有其他服务都将注册到至少一个 entrypoint
的 traefik 以获得请求。
因此您只需从 api 服务中删除 ports: - 80:3001
。
将会发生的是 traefik 只会监听端口 80,并且所有具有 domain.org
或 www.domain.org
的 http 主机 header 的 traefik 将被路由到应用程序服务所有带有 api.domain.org
的请求都将被路由到您的 api 服务。
如果您已完成上述操作但无法向您的 api 服务发送请求,请分享您服务中的一些日志以检查大多数情况下的错误,某些 header 需要传播后端服务,以便它们正常工作。
PS。您正在使用最新的 v2.0 版本的 traefik,显然将服务注册到入口点足以让 traefik 将请求路由到该服务。在以前的版本中,您应该向服务添加标签 traefik.port
以通告您的服务正在侦听的位置,这更明确地说明了正在发生的事情。 docs。
我有以下设置:
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
上同时提供 api
和 traefik
服务 运行?
实际上,您需要为 api 做您为应用程序所做的同样的事情,通过 traefik 公开它。
一般来说,您通常想要的是通过 traefik(或任何其他反向代理)公开所有集群内部服务,因此只有 traefik 应该公开主机的端口。您的所有其他服务都将注册到至少一个 entrypoint
的 traefik 以获得请求。
因此您只需从 api 服务中删除 ports: - 80:3001
。
将会发生的是 traefik 只会监听端口 80,并且所有具有 domain.org
或 www.domain.org
的 http 主机 header 的 traefik 将被路由到应用程序服务所有带有 api.domain.org
的请求都将被路由到您的 api 服务。
如果您已完成上述操作但无法向您的 api 服务发送请求,请分享您服务中的一些日志以检查大多数情况下的错误,某些 header 需要传播后端服务,以便它们正常工作。
PS。您正在使用最新的 v2.0 版本的 traefik,显然将服务注册到入口点足以让 traefik 将请求路由到该服务。在以前的版本中,您应该向服务添加标签 traefik.port
以通告您的服务正在侦听的位置,这更明确地说明了正在发生的事情。 docs。