0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何將多個容器暴露到一個端口上

dyquk4xk2p3d ? 來源:民工哥技術之路 ? 2023-11-29 14:30 ? 次閱讀

富 Web 時代,應用變得越來越強大,與此同時也越來越復雜。集群部署、隔離環(huán)境、灰度發(fā)布以及動態(tài)擴容缺一不可,而容器化則成為中間的必要橋梁。

IT 軟件中所說的 “Docker” ,是指容器化技術,用于支持創(chuàng)建和使用 Linux 容器。而 Docker 技術就是這樣一種神奇的存在:懂,萬物皆可容器化;不懂,則重復“搬磚”,繁忙而不自知。

我們的容器需要對外提供訪問的話,就是必須使用端口暴露。

Docker 容器暴露端口的形式有四種:

-p
#將指定的容器端口映射到宿主機所有地址的一個隨機端口

-p:
#將容器端口映射到指定的主機端口

-p::
#將容器端口映射到主機指定ip的隨機端口

-p::
#將容器端口映射到指定主機ip的指定端口

在日常工作環(huán)境中,我們會部署多個相同的服務來對外提供服務,這樣可以有效保證集群的高可用性,從而使用戶得到很好的體驗。

那么,如果多個容器提供一個服務,對外只暴露一個端口,怎么做呢?

通常有以下三種主流方法。

反向代理

當請求達到后,通過反向代理比如nginx、haproxy等,負載均衡的方式將流量轉發(fā)到后端不同的容器里面。對外就可以暴露一個端口了。72a7e9ee-8e7f-11ee-939d-92fbcf53809c.png

步驟一:創(chuàng)建一個網(wǎng)絡

首先,我們需要創(chuàng)建一個網(wǎng)絡,使得多個容器能夠相互通信。我們可以使用Docker命令docker network create來創(chuàng)建網(wǎng)絡。下面是創(chuàng)建一個名為my-network的網(wǎng)絡的代碼示例:

dockernetworkcreatemy-network

這將創(chuàng)建一個名為my-network的網(wǎng)絡,供后續(xù)的容器使用。

啟動多個容器

接下來,我們需要啟動多個容器,并將它們連接到之前創(chuàng)建的網(wǎng)絡上。同時,我們需要將容器的端口映射到宿主機的端口上,以便外部可以訪問。以下是啟動三個容器并進行端口映射的代碼示例:

dockerrun-d--networkmy-network--namecontainer1-p8080:80image1
dockerrun-d--networkmy-network--namecontainer2-p8080:80image2
dockerrun-d--networkmy-network--namecontainer3-p8080:80image3

上述代碼中,我們使用docker run命令分別啟動了三個容器,并指定了容器的網(wǎng)絡為my-network。--name參數(shù)用于指定容器的名稱,-p參數(shù)用于進行端口映射,將容器的80端口映射到宿主機的8080端口上。

步驟三:配置負載均衡

最后,我們需要配置一個負載均衡容器,將外部對于宿主機的訪問請求分發(fā)到多個容器上。在本示例中,我們使用了Nginx作為負載均衡容器。以下是配置負載均衡容器的代碼示例:

dockerrun-d--networkmy-network-p8080:80--nameload-balancernginx

上述代碼中,我們使用docker run命令啟動了一個Nginx容器,并將容器的網(wǎng)絡設置為my-network。-p參數(shù)用于進行端口映射,將容器的80端口映射到宿主機的8080端口上。

DNAT

熟悉k8s Nodeport 實現(xiàn)的話就會發(fā)現(xiàn),k8s里面service iptables 實現(xiàn)就是基于DNAT。關于k8s Nodeport的實現(xiàn)參見之前k8s的文章。我們可以先通過docker 命令啟動兩個容器:

$CONT_PORT=9090

$dockerrun-d--rm
--namehttp_server_foo
-eINSTANCE=foo
-ePORT=$CONT_PORT
http_server

$dockerrun-d--rm
--namehttp_server_bar
-eINSTANCE=bar
-ePORT=$CONT_PORT
http_server

獲取這個兩個容器的IP

$CONT_FOO_IP=$(dockerinspect-f'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'http_server_foo)
$echo$CONT_FOO_IP
172.17.0.2

$CONT_BAR_IP=$(dockerinspect-f'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'http_server_bar)
$echo$CONT_BAR_IP
172.17.0.3

然后創(chuàng)建 DNAT 規(guī)則

$FRONT_PORT=80

#Notsecure!UseglobalACCEPTonlyfortests.
$sudoiptables-IFORWARD1-jACCEPT

#DNAT本地流量,宿主機訪問
$sudoiptables-tnat-IOUTPUT1-ptcp--dport$FRONT_PORT
-mstatistic--moderandom--probability1.0
-jDNAT--to-destination$CONT_FOO_IP:$CONT_PORT

$sudoiptables-tnat-IOUTPUT1-ptcp--dport$FRONT_PORT
-mstatistic--moderandom--probability0.5
-jDNAT--to-destination$CONT_BAR_IP:$CONT_PORT

#DNAT外部流量,其他機器訪問
$sudoiptables-tnat-IPREROUTING1-ptcp--dport$FRONT_PORT
-mstatistic--moderandom--probability1.0
-jDNAT--to-destination$CONT_FOO_IP:$CONT_PORT

$sudoiptables-tnat-IPREROUTING1-ptcp--dport$FRONT_PORT
-mstatistic--moderandom--probability0.5
-jDNAT--to-destination$CONT_BAR_IP:$CONT_PORT

通過上面模仿k8s Nodeport的實現(xiàn),就是可以輕松實現(xiàn)一個端口對應多個容器了。

多服務監(jiān)聽

這個方法稍微hack 一點,其實 socket 在listen 的時候,支持 SO_REUSEPORT ,它的效果是運行多個程序監(jiān)聽同一個端口。

funcmain(){
lc:=net.ListenConfig{
Control:func(network,addressstring,connsyscall.RawConn)error{
varoperrerror
iferr:=conn.Control(func(fduintptr){
operr=syscall.SetsockoptInt(
int(fd),
unix.SOL_SOCKET,
unix.SO_REUSEPORT,
1,
)
});err!=nil{
returnerr
}
returnoperr
},
}

ln,err:=lc.Listen(
context.Background(),
"tcp",
os.Getenv("HOST")+":"+os.Getenv("PORT"),
)
iferr!=nil{
panic(err)
}

http.HandleFunc("/",func(whttp.ResponseWriter,_req*http.Request){
w.Write([]byte(fmt.Sprintf("Hellofrom%s
",os.Getenv("INSTANCE"))))
})

iferr:=http.Serve(ln,nil);err!=nil{
panic(err)
}
}

這個我們就啟動多個容器,共享 network namespace,同時監(jiān)聽這個端口了。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 網(wǎng)絡
    +關注

    關注

    14

    文章

    7449

    瀏覽量

    88468
  • 主機
    +關注

    關注

    0

    文章

    973

    瀏覽量

    34971
  • 端口
    +關注

    關注

    4

    文章

    936

    瀏覽量

    31958
  • 容器
    +關注

    關注

    0

    文章

    491

    瀏覽量

    22015
  • Docker
    +關注

    關注

    0

    文章

    447

    瀏覽量

    11781

原文標題:面試官:如何將多個容器暴露到一個端口上?問倒一大片。。。

文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何通過已占用的端口號找到占用端口容器

    已啟動了N多個容器Linux操作系統(tǒng)的宿主機上,新啟動映射到宿主機
    的頭像 發(fā)表于 07-26 08:45 ?7045次閱讀
    如何通過已占用的<b class='flag-5'>端口</b>號找到占用<b class='flag-5'>端口</b>的<b class='flag-5'>容器</b>?

    ADXL345如何將端口INT1重置為原始低電平?

    我用ADXL345在INT1端口上配置了雙擊中斷,但是雙擊后觸發(fā)了。INT1端口的值直保持在高電平,沒有回到低電平。我想知道如何將端口 I
    發(fā)表于 12-27 07:44

    如何將Strut暴露給程序的其他部分?

    在頭文件(使用EXTEN)中聲明變量,在這種情況下,如何將Strut暴露給程序的其他部分?如果我想在整個程序中訪問頭文件中的這個聲明,我不需要在同
    發(fā)表于 08-02 10:27

    如何將分區(qū)劃分為可讀分區(qū)?

    我們設計了基于USB SD3的自定義板。我們已經(jīng)移植的例子說明了使用FX3S固件API來實現(xiàn)大容量存儲類設備,它允許訪問連接到SD3的SD/MMC設備。應用程序存儲端口上找到的存儲設備劃分為兩
    發(fā)表于 09-27 14:22

    如何將多個LabVIEW生成的exe打包進同一個安裝包??

    我用labview寫了軟件,生成了多個版本的exe,如何將多個exe打包一個安裝包中。在安
    發(fā)表于 11-14 10:50

    如何將輸出重定向不同的UART

    a)當使用和聲時,我可以Prtuf直接指向任意的UART,或者總是指向UART2?如果是,我如何將輸出重定向不同的UART?B)和聲
    發(fā)表于 05-06 13:59

    如何將freemodbus移植stm32平臺

    modbus是非常好的串口協(xié)議(當然也能用在網(wǎng)口上),它簡潔、規(guī)范、強大??梢詽M足大部分的工業(yè)、嵌入式需求。這里詳細說下如何將freemodbus移植
    發(fā)表于 08-16 06:59

    如何將多個模塊的代碼合并到工程里?

    如何將多個模塊的代碼合并到工程里?
    發(fā)表于 11-18 07:39

    如何將CubeMX LSM303AH連接到I2C接口上呢?

    如何將CubeMX LSM303AH連接到I2C接口上呢?求大神告知
    發(fā)表于 12-16 06:44

    如何將按鈕回調從小容器傳播到容器中的當前視圖呢?

    組相同的小型自定義容器放入容器中。然后我
    發(fā)表于 12-26 06:19

    如何將alpha值設置為模擬時鐘或容器

    我想在所有屏幕的背景上制作透明時鐘。所以我認為 Alpha 值是在兩屏幕上實現(xiàn)透明的唯方法。模擬時鐘和容器在他們的庫中沒有 Alph
    發(fā)表于 02-07 07:01

    針對UART通信端口上射頻干擾的研究

    針對UART通信端口上射頻干擾的研究 有客戶報告其中心位于840MHz左右的RF干擾影響配置成UART的串行通信端口,該接口位于包含AD6903(LeMansLCR+)數(shù)字
    發(fā)表于 04-20 16:54 ?1211次閱讀
    針對UART通信<b class='flag-5'>端口上</b>射頻干擾的研究

    如何將1多個Arduino與樹莓派結合使用

    僅使用Arduino您可以在關閉電源的情況下Arduino插入任何USB端口,然后它將正常工作。
    的頭像 發(fā)表于 11-19 11:12 ?4908次閱讀
    <b class='flag-5'>如何將</b>1<b class='flag-5'>個</b>或<b class='flag-5'>多個</b>Arduino與樹莓派結合使用

    如何將USB Type-C端口裝入墻上插座

    隨著USB Type-C成為電子設備的主流充電接口,設計工程師面臨著挑戰(zhàn):如何將越來越高功率的USB Type-C端口裝入空間和散熱能力有限的墻上插座?這里分享
    的頭像 發(fā)表于 04-06 17:58 ?1.4w次閱讀

    如何將linux下多種類型的多個文件復制一個目錄

    即假如/haodao1目錄下存在test1.txt、test2.c、test3.java、test4.py、test5.sql這五種不同類型的不同文件,如何將.txt、.c、.java、.py這些文件類型的多個文件拷貝/hao
    發(fā)表于 06-09 15:44 ?959次閱讀