網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
docker部署golang?http服務(wù)時(shí)端口無(wú)法訪(fǎng)問(wèn)的問(wèn)題解決_docker
作者:冬天里的懶貓 ? 更新時(shí)間: 2022-09-30 編程語(yǔ)言需要使用docker將golang的httpserver容器化。在這個(gè)過(guò)程中遇到了一個(gè)低級(jí)問(wèn)題,golang http服務(wù)時(shí)端口無(wú)法訪(fǎng)問(wèn),特此記錄解決這個(gè)問(wèn)題的過(guò)程。
1.背景
1.1 問(wèn)題描述
問(wèn)題描述: docker鏡像啟動(dòng)成果之后,通過(guò)curl不能訪(fǎng)問(wèn):
[root@hecs-205828 ~]# curl -XGET http://127.0.0.1:8360/hello
curl: (56) Recv failure: Connection reset by peer
1.2 webserver代碼
go文件:main.go
package main import ( "fmt" "net/http" "os" "strings" ) func main() { http.HandleFunc("/hello", handler_hello) http.HandleFunc("/healthz", handler_healthz) http.ListenAndServe("127.0.0.1:8360", nil) } func handler_healthz(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } func handler_hello(w http.ResponseWriter, r *http.Request) { fmt.Println("method = ", r.Method) fmt.Println("URL = ", r.URL) fmt.Println("RemoteAddr = ", r.RemoteAddr) fmt.Println("IP = ", strings.Split(r.RemoteAddr, ":")[0]) fmt.Println("header = ", r.Header) fmt.Println("body = ", r.Body) fmt.Println(r.RemoteAddr, "連接成功") for name, values := range r.Header { for _, value := range values { fmt.Println(name, value) _, exits := w.Header()[name] if exits { w.Header().Add(name, value) } else { w.Header().Set(name, value) } } } VERSION := os.Getenv("VERSION") fmt.Println("VERSION is :", VERSION) w.Header().Set("VERSION", VERSION) w.WriteHeader(http.StatusOK) w.Write([]byte("hello http server")) }
3.Dockerfile文件
Dockerfile文件:
FROM golang:1.17 AS build
WORKDIR /web-server/
COPY . .
ENV CGO_ENABLED=0
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn,direct
RUN GOOS=linux go build -installsuffix cgo -o web-server main.go
FROM busybox
COPY --from=build /web-server/web-server /web-server/web-server
EXPOSE 8360
ENV ENV local
WORKDIR /web-server/
ENTRYPOINT ["/web-server/web-server"]
2.問(wèn)題分析
發(fā)現(xiàn)curl無(wú)法訪(fǎng)問(wèn)docker容器中的服務(wù),telnet結(jié)果如下:
[root@hecs-205828 ~]# telnet 127.0.0.1 8360
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.
于是,打算采用命令進(jìn)入docker容器內(nèi)部查看:
[root@hecs-205828 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfb2b46abd34 httpserver:0.0.1 "/web-server/web-ser…" 27 hours ago Up 2 hours 0.0.0.0:8360->8360/tcp, :::8360->8360/tcp relaxed_mccarthy
通過(guò)docer ps -a 得到容器id為dfb2b46abd34。進(jìn)入容器:
[root@hecs-205828 ~]# docker exec -it dfb2b46abd34 sh
/web-server # ps
PID USER TIME COMMAND
1 root 0:00 /web-server/web-server
38 root 0:00 sh
94 root 0:00 sh
101 root 0:00 ps
/web-server # netstat -an |grep 8360
tcp 0 0 127.0.0.1:8360 0.0.0.0:* LISTEN
/web-server #
可以看到,在容器內(nèi)部實(shí)際上8360端口已經(jīng)被監(jiān)聽(tīng)。容器訪(fǎng)問(wèn)應(yīng)該不存在問(wèn)題。 容器內(nèi)部支持wget:
/web-server # wget -q -O - http://127.0.0.1:8360/hello
hello http server
/web-server #
可以看到在docker服務(wù)內(nèi)部運(yùn)行是正常的。
查看其網(wǎng)絡(luò)端口衍射:
[root@hecs-205828 ~]# docker port dfb2b46abd34
8360/tcp -> 0.0.0.0:8360
8360/tcp -> :::8360
端口衍射也不存在問(wèn)題。那么問(wèn)題究竟出在什么地方呢? 忽然想到,容器內(nèi)部的nestat監(jiān)聽(tīng)端口是127.0.0.1,于是瞬間明白了。 在容器內(nèi)部的監(jiān)聽(tīng)端口為127.0.0.1的話(huà),那么只能接受容器內(nèi)部來(lái)自127.0.0.1的本地回環(huán)訪(fǎng)問(wèn)。來(lái)自容器外外部的訪(fǎng)問(wèn)請(qǐng)求將被拒絕。 因此,這個(gè)問(wèn)題的修復(fù)原因?qū)嶋H上很簡(jiǎn)單,只需要將main.go的中監(jiān)聽(tīng)ip改為0.0.0.0即可。
3.解決方案
果斷將監(jiān)聽(tīng)ip改為0.0.0.0:
func main() { http.HandleFunc("/hello", handler_hello) http.HandleFunc("/healthz", handler_healthz) http.ListenAndServe("0.0.0.0:8360", nil) }
之后重新制作鏡像:
sudo docker build . -t httpserver:0.0.2
然后啟動(dòng)本地鏡像:
sudo docker run -d -p 8260:8230 httpserver:0.0.2
啟動(dòng)之后:
[root@hecs-205828 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae5e2bf431c7 httpserver:0.0.2 "/web-server/web-ser…" 50 minutes ago Up 50 minutes 0.0.0.0:8260->8360/tcp, :::8260->8360/tcp affectionate_nash
dfb2b46abd34 httpserver:0.0.1 "/web-server/web-ser…" 27 hours ago Up 2 hours 0.0.0.0:8360->8360/tcp, :::8360->8360/tcp relaxed_mccarthy
[root@hecs-205828 ~]#
之后再訪(fǎng)問(wèn)新增的容器,結(jié)果正常:
[root@hecs-205828 ~]# curl -XGET http://127.0.0.1:8260/hello
hello http server
[root@hecs-205828 ~]#
問(wèn)題解決。
原文鏈接:https://juejin.cn/post/7128165664610598943
相關(guān)推薦
- 2022-07-22 數(shù)據(jù)庫(kù)常見(jiàn)約束
- 2022-07-02 C++精要分析右值引用與完美轉(zhuǎn)發(fā)的應(yīng)用_C 語(yǔ)言
- 2022-07-28 Go語(yǔ)言反射reflect.Value實(shí)現(xiàn)方法的調(diào)用_Golang
- 2022-11-12 超詳細(xì)解析C++實(shí)現(xiàn)快速排序算法的方法_C 語(yǔ)言
- 2022-07-14 Android實(shí)現(xiàn)手勢(shì)劃定區(qū)域裁剪圖片_Android
- 2022-08-21 Android使用貝塞爾曲線(xiàn)畫(huà)心形_Android
- 2022-12-04 Flutter組件適配方法實(shí)現(xiàn)詳解_Android
- 2022-02-23 IDEA git 拉取項(xiàng)目時(shí)報(bào) No tracked branch configured for b
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支