問題描述
在容器中運(yùn)行一個websocket client時,連接websocket server失敗,并且無報錯信息。
建立websocket連接的代碼為:
// var wsAdapterEndpoint = "wss://openbot.xxxx-inc.com/ws"
func (l *GuardBot) setupWebsocketConn() error {
c, rsp, err := websocket.DefaultDialer.Dial(wsAdapterEndpoint, nil)
if err != nil {
logger.Fatalf("failed to connect ws, endpoint: %v, error: %v", wsAdapterEndpoint, rsp)
return err
}
l.conn = c
return nil
}
報錯信息如下:
setupWebsocketConn() failed to connect ws, endpoint: wss://openbot.xxxx-inc.com/ws, error: <nil>
問題分析
- 該程序在本地host上直接運(yùn)行是正常的,可以成功連到websocket server。
- 容器中啟動該程序時,連接失敗。使用
telnet openbot.xxxx-inc.com
命令發(fā)現(xiàn)其IP和本地解析出來的的IP地址是一樣的,排除了網(wǎng)絡(luò)域名解析問題。
由于缺乏error日志,只能一點(diǎn)點(diǎn)排查了。在容器內(nèi)使用命令apt-get install curl
后,直接啟動執(zhí)行文件竟然可以連接成功websocket server了。看了下apt-get install curl
的日志,發(fā)現(xiàn)有openssl和ca證書相關(guān)組件也被安裝了。恰好我們使用的websocket連接是加密過的(wss連接),極大可能就是由這個引起的。
于是重啟了一把容器,在容器內(nèi)手動安裝了openssl和ca工具包,手動執(zhí)行程序發(fā)現(xiàn)果然可以連接websocket server成功。
問題解決
Dockerfile中構(gòu)建鏡像時,添加openssl和證書相關(guān)工具包即可。啟動容器發(fā)現(xiàn)可以正常連接到websocket server。
FROM debian:buster-slim
RUN apt-get update && apt-get install -y openssl ca-certificates
...
其他
沒想到debian的基礎(chǔ)鏡像連ca證書包都精簡掉了,剛好碰到github.com/gorilla/websocket
包連接wss缺少ca時沒有報錯信息。這次問題也算是瞎貓碰到死耗子。
不過還是可以靠排除法來逐步縮小范圍,譬如把websocket server端不使用tls,直接用ws連接,這樣容器內(nèi)應(yīng)該就能連上websocket,從而判斷出是tls、證書相關(guān)問題。
有時間還是要看一下github.com/gorilla/websocket
包的源碼,分析下為啥這種場景沒有error日志。