我试着用Docker连接我服务,以便学习。
当我在我的本地主机上尝试时,一切都很好。
但是当我在Docker上尝试它时,当我尝试从产品服务到我的授权服务进行http重定向时,它会出错。
我所尝试的是使用http重定向,我向auth-service发出一个新的请求,它工作并连接,但当我尝试在Docker中重定向它时,它会出错。
这是我的重定向代码
我在用golang和Gin-gonic图书馆
url := os.Getenv("AUTH_SERVICE_URL") // http://auth-service:8081
c.Redirect(http.StatusSeeOther, url+"/refresh?token="+tokenStr)
c.Abort()
return
这是我的新请求代码
url := os.Getenv("AUTH_SERVICE_URL") // http://auth-service:8081
request, err := http.NewRequest(http.MethodGet, url+"/refresh?token="+tokenStr, nil)
log.Println("make request to", request.URL)
if err != nil {
panic("Internal Server Error")
}
client := http.Client{
Timeout: 30 * time.Second,
}
response, err := client.Do(request)
if err != nil {
panic(fmt.Sprint("unable to get auth request", err.Error()))
}
log.Println("REFRESH TOKEN", response.Header)
我只是想知道,为什么当我使用http重定向它有一个错误的Docker,但它的工作时,我尝试在我的本地主机。
我正在使用postman进行测试,但遇到此错误。Error: getaddrinfo ENOTFOUND auth-service
但是当我在我的Docker中使用相同URL的新Http请求代码时,它可以工作。
这是我的产品服务对接组合
version: '3'
services:
product-service:
build:
context: .
dockerfile: .
ports:
- "8082:8082"
environment:
AUTH_SERVICE_URL: http://auth-service:8081
DB_DRIVER: postgres
DB_USER: postgres
DB_PASSWORD: password
DB_HOST: postgresDB
DB_PORT: 5431
DB_NAME: v_product
DB_SSL_MODE: disable
PORT: 8082
networks:
- auth-service_default
- product-service_default
depends_on:
- postgresDB
postgresDB:
image: 'postgres:12.12'
ports:
- "5431:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: v_product
networks:
- product-service_default
volumes:
- psql_user:/var/lib/postgresql/data
volumes:
psql_user:
networks:
auth-service_default:
external: true
product-service_default:
external: true
这是我的身份验证服务
version: '3'
services:
auth-service:
build:
context: .
dockerfile: .
ports:
- "8081:8081"
environment:
USER_SERVICE_URL: http://user-service:8080
PORT: 8081
networks:
- user-service_default
- auth-service_default
networks:
user-service_default:
external: true
auth-service_default:
external: true
注意:我尝试重新导向的端点是:GET
:8081/refresh?token=JWTOKEN
,我使用See Other
代码进行重定向,因为它是从POST
请求重定向的。
1条答案
按热度按时间rnmwe5a21#
一个HTTP Redirect的工作原理如下(参见链接以获得更好的图表描述等):
1.客户端(例如 Postman )发出请求(例如
GET http://auth-service:8080
)1.服务器以重定向状态(本例中为
303
“See Other”)和新URL(例如http://auth-service:8081/refresh?token=blah
)进行响应1.客户端请求新的URL。
所以,根据评论,你的应用程序被重定向到
http://auth-service:8081/refresh?token=blah
。问题是,当客户端,这不是一个容器,尝试查找主机auth-service
的IP地址,但找不到(它不在本地的hosts
文件中,无论您使用的是什么DNS服务器,它都不知道该地址)。(例如http://127.0.0.1:8081
)。即使客户端可以解析
auth-service
,地址也可能是类似172.21.0.2
的地址,这是一个无法从主机访问的私有地址,这一点毫无意义(因为您使用的是网桥网络)。这种类型的网络允许container在它们之间进行通信(在限制内)并发起传出连接,但不为主机或连接到主机的设备提供入站访问。外部访问(通常)通过已发布的端口;即
docker-compose.yml
中的ports: - "5431:5432"
行。这些条目允许您公开主机上的container端口(在本例中,container上的端口5432
公开为主机上的端口5432
,但端口号可以不同)。1.集装箱中的网络是如何工作的
抱歉--在堆栈溢出的答案中解释太多了!docker docs非常好。
1.5它是否对我的重定向操作生效,或者我只是错误地指定了主机,因为重定向是由客户端执行的?
重定向使用http协议执行。HTTP是application layer协议;通信通常通过TCP/IP连接进行。花点时间了解所有涉及的不同层是值得的(IT中总是有更多东西需要学习!)。
在底层TCP栈中,主机(和其他外部系统)只能通过发布的端口访问容器。DNS(主机名如何Map到IP)和IP路由(主机的流量能否到达容器)是两个独立的考虑因素,这毫无意义。
1.这个案子的委托人是 Postman 对吗
Postman 是好的。另一种选择是使用浏览器,它的操作方式大致相同。
1.如果我说当容器尝试与命名主机服务连接时,如果每个容器连接到相同的网络,就可以完成通信,这与服务器到服务器的通信相同,我说得对吗?
同一网络上的容器可以通信,Docker提供了一个嵌入式DNS服务器,使它们能够执行查找(因此将
auth-service
Map到容器的IP地址,将host.docker.internal
Map到主机)。需要注意的是,主机不使用此嵌入式DNS服务器(并且无论如何使用都是有限的,因为主机无法通过容器的IP地址直接与容器通信)。希望这能有所帮助-这可能会让人很困惑,特别是如果你没有太多的网络经验。我会注意到,我经常在这种情况下使用边缘路由器/反向代理(例如Traefik)。使用此选项,您可以仅Map一个端口(如果需要HTTPS,则可能需要两个),Traefik将请求路由到相应的容器(这可能只是让你现在感到困惑,但在未来可能会很有用!)。