Docker 提供多種網路模式,影響容器的網路行為。可以讓容器與 Docker 主機共用網路,或完全隔離。none 網路不提供任何網路介面,bridge 網路則為單一主機上的預設網路,透過 docker0 介面路由。自訂網路允許建立隔離的網路環境,而 Docker Swarm 的 Overlay 網路則可建立跨主機網路。服務暴露可透過 -p 選項發布容器埠,方便外部存取。除錯網路問題時,可使用 netstat、telnet、strace 等工具。設定 DNS 可透過 –dns 選項指定伺服器,或使用 dnsmasq 覆寫 DNS 條目。容器內傳送郵件可使用主機郵件服務或安裝 ssmtp。
VII. 連線埠繫結 - 透過連線埠繫結匯出服務
在 Docker 和網路相關的應用中,容器執行的網路模式有多種,這些模式對於容器的網路行為有著重要的影響。你可以選擇讓容器與 Docker 主機共用相同的網路,或者完全隔離容器的網路。這種行為取決於所使用的網路驅動程式。
使用 Docker 時,你可以定義自己的使用者自定義網路。這些網路可以在單一主機上建立,也可以跨越多個主機(Docker Swarm)。預設情況下,Docker 會建立幾個網路:
Docker 網路型別
none 網路:此網路不會為容器新增任何網路介面,這意味著容器內的程式無法使用任何網路功能。容器無法連線到網際網路,也無法將服務暴露給其他容器。
# docker run --rm -it --network=none alpine:3.5 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever如上所示,只有「lo」(迴路/本地端)介面可在容器中使用。這種網路模式適用於執行不可信任的程式碼,或者你知道某些 CLI 應用程式不應該具有網際網路存取許可權的情況。
bridge 網路:這是你在單一主機上執行 Docker 容器時的預設網路。此網路透過 Docker 主機上的 docker0 介面進行路由。
如果你在預設網路上執行多個容器,它們無法透過 DNS 互相看到對方,但如果你知道其他容器的 IP,就可以 ping/連線到它們。
# docker run -itd --name sh1 alpine:3.5 sh # docker run -itd --name sh2 alpine:3.5 sh # docker run --rm -it alpine:3.5 ping sh1 ping: bad address 'sh1'但是,你可以 ping/連線到相同網路上的其他容器(如果知道其 IP)。
# docker exec -it sh1 ip addr | grep global inet 172.17.0.3/16 scope global eth0 # docker exec -it sh2 ip addr | grep global inet 172.17.0.4/16 scope global eth0 # docker exec -it sh2 ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3): 56 data bytes 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.167 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.111 ms ^C從這些容器中可以自由存取網際網路,因此你可以擷取網際網路上的套件、取用公開的 API 服務或連線到相同私有區域網路中的其他主機。
內容解密:
- Docker 網路型別包括 none 和 bridge 等。
- none 網路使容器完全隔離於網路,而 bridge 網路則允許容器間的通訊(透過 IP 位址)並可存取網際網路。
- 正確選擇網路模式對於確保容器的安全性和功能性至關重要。
Docker Swarm 與服務擴充套件
Docker Swarm 是 Docker 的叢集管理工具,允許你將多個 Docker 主機組成一個虛擬的 Docker 主機。在上述範例中,我們使用 Docker Swarm 建立了一個具有多個副本的 sonyflake 服務,並對其進行了效能測試。
# docker service create \
--replicas 5 \
--network party-swarm \
--update-parallelism 5 \
--name sonyflake \
-p 80:80 titpetric/sonyflake
內容解密:
- 使用 Docker Swarm 可以輕鬆地擴充套件服務。
--replicas引數用於指定服務的副本數量。--network引數指定服務所使用的網路。-p引數進行主機與容器的連線埠對應。
自定義網路與服務暴露:深入解析 Docker 網路架構
Docker 的網路功能是其重要的組成部分,允許容器之間進行通訊以及與外部網路互動。本文將探討 Docker 的自定義網路、跨主機網路以及主機網路模式,提供技術深度與實務經驗的分析。
自定義橋接網路
自定義橋接網路允許使用者建立多個隔離的網路環境,讓容器可以在特定的網路中進行通訊。建立自定義橋接網路的指令如下:
docker network create -d bridge --subnet 172.25.0.0/24 party
此指令建立了一個名為 party 的橋接網路,使用 172.25.0.0/24 子網。這種網路與預設的橋接網路不同,連線到此網路的容器可以透過 Docker 內部的 DNS 服務互相解析對方的名稱。
內容解密:
docker network create:建立新的 Docker 網路。-d bridge:指定網路驅動程式為橋接模式。--subnet 172.25.0.0/24:指定子網範圍。party:自定義網路的名稱。
建立兩個容器並測試它們之間的連通性:
docker run -itd --name sh1 --network party alpine:3.5 sh
docker run -itd --name sh2 --network party alpine:3.5 sh
docker exec -it sh2 ping sh1
內容解密:
docker run -itd --name sh1 --network party alpine:3.5 sh:以分離模式執行一個名為sh1的容器,並連線到party網路。docker exec -it sh2 ping sh1:在sh2容器中執行ping命令測試與sh1的連通性。
跨主機網路
在 Docker Swarm 模式下,可以使用 Overlay 網路驅動程式建立跨主機的網路。這種網路允許不同主機上的容器進行通訊。
建立 Overlay 網路的指令如下:
docker network create \
--driver overlay \
--subnet 10.0.0.0/20 \
--attachable \
party-swarm
內容解密:
--driver overlay:指定使用 Overlay 網路驅動程式。--subnet 10.0.0.0/20:指定較大的子網範圍以支援更多的容器。--attachable:允許非 Swarm 服務的容器連線到此網路。
在不同主機上執行容器並測試它們之間的連通性:
ssh swarm2 docker run -itd --name sh1 --network party-swarm alpine:3.5 sh
ssh swarm3 docker run -itd --name sh2 --network party-swarm alpine:3.5 sh
docker run -it --rm --network party-swarm alpine:3.5 nslookup sh1
內容解密:
ssh swarm2 docker run ...:在遠端主機swarm2上執行容器。docker run -it --rm --network party-swarm alpine:3.5 nslookup sh1:在當前主機上執行容器並解析sh1的名稱。
主機網路模式
主機網路模式讓容器分享主機的網路堆疊,提供完全的網路存取許可權。這對於需要高度網路存取許可權的應用(如 VPN 使用者端或網路監控工具)非常有用。
執行容器時使用 --net=host 選項即可啟用主機網路模式:
docker run --net=host my-vpn-client
內容解密:
--net=host:啟用主機網路模式,讓容器分享主機的網路堆疊。
透過埠繫結(Port Binding)匯出服務
暴露服務埠
執行服務的建議方式是將容器附加到自訂的橋接網路(bridge network)或疊加網路(overlay network),取決於您是使用 Docker 還是 Swarm 服務來呼叫容器。無論採用哪種方式,都可以透過 -p 選項公開個別埠。
檢視第四章的 Redis 範例,您會注意到沒有公開任何埠。Redis 是一個私有的服務,執行在我們的內部網路上,這意味著同一個網路上的其他容器可以存取它,而無需 Docker 設定代理。
當您明確想要發布服務埠時,只有一個選項:
使用 -p 選項發布容器埠
格式如下:
ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
hostPort 和 containerPort 都可以指定為埠範圍。當為兩者指定範圍時,容器埠範圍內的埠數量必須與主機埠範圍內的埠數量相匹配,例如:
-p 1234-1236:1234-1236/tcp
當僅指定 hostPort 的範圍時,containerPort 不能是範圍。在這種情況下,容器埠會被發布到指定的 hostPort 範圍內的某個埠,例如:
-p 1234-1236:1234/tcp
假設您的應用程式監聽埠 3000,但您想暴露埠 80,您可以傳遞 -p 80:3000。這使得執行不完全符合 12FA 規範的應用程式變得更加容易,您無法透過環境變數設定其埠。
除錯 Docker 網路連線
除錯網路連線問題時,通常會檢查幾個方面。在 Debian 中,有一個名為 net-tools 的套件,提供了 netstat 工具。使用它,可以輕鬆檢查給定的服務是否正在監聽某個埠。例如,要了解您的 Docker 應用程式正在繫結哪些內部服務埠,可以執行:
docker exec -it apt-cacher netstat -pan
輸出範例:
Active Internet connections (servers and established)
Proto Local Address Foreign Address State PID/Program name
tcp 127.0.0.11:37391 0.0.0.0:* LISTEN -
tcp 0.0.0.0:3142 0.0.0.0:* LISTEN 7/apt-cacher-ng
tcp6 :::3142 :::* LISTEN 7/apt-cacher-ng
udp 127.0.0.11:32837 0.0.0.0:* -
您可以選擇附加 | grep LISTEN 以僅檢視正在監聽傳入連線的埠。這裡,我們有一個 apt-cacher-ng 的例項,它正在 IPv4 和 IPv6 上監聽埠 3142。
Linux 中可用的網路除錯工具
Linux 中有多種工具可用於除錯網路連線和程式執行。至少應該對以下工具有所瞭解:
telnet、netcat:開啟到 IP/主機和埠的原始連線(TCP)curl、wget:向端點發出 HTTP 請求netcat、ss:列出開啟的連線、列出監聽的通訊端lsof:列出正在執行的程式開啟的檔案strace:列印您執行的程式的系統呼叫軌跡
尤其是 strace,在除錯網路連線問題時可能非常有用。曾經遇到過連線到在 Docker 中執行的資料函式庫例項需要幾秒鐘的時間。使用了 telnet 後,發現連線到 MySQL 的時間延遲是由於 DNS 解析問題引起的。使用 strace 後,發現了 /etc/resolv.conf 中的 search mtk.lan 選項導致了延遲。重新啟動 Docker 守護程式後,問題得以解決。
使用 Plantuml 圖表呈現網路架構
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 使用 Plantuml 圖表呈現網路架構
rectangle "監聽埠 3000" as node1
rectangle "暴露埠 80" as node2
rectangle "反向代理" as node3
node1 --> node2
node2 --> node3
@enduml此圖示呈現了應用程式、容器和主機之間的關係,以及如何透過暴露埠和反向代理來處理外部請求。
詳細說明
透過使用 -p 選項,可以將容器的埠對映到主機的埠,使得外部可以存取容器內的服務。在除錯網路連線問題時,可以使用多種 Linux 工具,如 netstat、telnet、strace 等。這些工具可以幫助您瞭解容器的網路組態、檢查服務是否正在監聽特定的埠、以及除錯網路延遲等問題。
自訂DNS與郵件傳送在Docker中的應用
在Docker容器中,有時需要自訂DNS伺服器或傳送郵件。本文將介紹如何在Docker中使用自訂DNS以及如何設定郵件傳送。
使用自訂DNS
Docker提供了--dns選項,允許使用者指定容器使用的DNS伺服器。例如:
docker run -it --rm=true --dns 8.8.8.8 alpine:3.5 ping www.google.com
內容解密:
docker run:啟動一個新的Docker容器。-it:分配一個偽TTY,並保持STDIN開啟,允許與容器互動。--rm=true:當容器離開時自動刪除容器。--dns 8.8.8.8:指定容器使用Google的公共DNS伺服器(8.8.8.8)。alpine:3.5:使用Alpine Linux 3.5作為容器基礎映像。ping www.google.com:在容器內執行ping命令測試網路連線。
此外,還可以使用janeczku/go-dnsmasq來執行一個開發用的DNS伺服器,並覆寫某些公共DNS條目。例如:
#!/bin/bash
NAME="dnsmasq"
DOCKERFILE="janeczku/go-dnsmasq:latest"
PARENT=$(dirname $(dirname $(realpath -s $0)))
docker rm -f $NAME
docker run --restart=always -d -h $NAME --name $NAME -p 53:53/udp -p 53:53 -v $PARENT/conf:/conf $DOCKERFILE -f /conf/hosts --verbose -n 8.8.8.8,8.8.4.4
內容解密:
docker rm -f $NAME:強制刪除名為$NAME的容器。docker run:啟動一個新的容器。--restart=always:設定容器總是重啟。-d:以分離模式執行容器。-h $NAME:設定容器的主機名。--name $NAME:命名容器。-p 53:53/udp -p 53:53:將主機的53埠(TCP和UDP)對映到容器的53埠,用於DNS服務。-v $PARENT/conf:/conf:掛載主機的組態目錄到容器的/conf目錄。$DOCKERFILE:使用指定的Docker映像。-f /conf/hosts --verbose -n 8.8.8.8,8.8.4.4:指定dnsmasq的組態檔案和上游DNS伺服器。
傳送郵件
在Docker容器中傳送郵件有多種方法。最簡單的方法是使用主機上的郵件服務,或在容器中安裝ssmtp。
使用主機上的郵件服務
可以透過--add-host選項將主機的郵件服務對映到容器內。例如:
--add-host docker:172.25.0.1 --add-host mail:172.25.0.1 --add-host $(uname -n):172.25.0.1
內容解密:
--add-host:在容器的/etc/hosts檔案中新增主機名到IP的對映。docker:172.25.0.1、mail:172.25.0.1、$(uname -n):172.25.0.1:將指定的主機名對映到IP172.25.0.1。
在容器中安裝ssmtp
在根據Alpine的容器中,可以透過以下命令安裝ssmtp:
apk --update add ssmtp
內容解密:
apk:Alpine的包管理工具。--update:更新包索引。add ssmtp:安裝ssmtp包。
安裝後,可以透過環境變陣列態ssmtp:
cat << EOF > /etc/ssmtp/ssmtp.conf
mailhub=$SSMTP_SERVER:$SSMTP_PORT
AuthUser=$SSMTP_USER
AuthPass=$SSMTP_PASS
UseSTARTTLS=$SSMTP_TLS
hostname=$SSMTP_HOSTNAME
FromLineOverride=YES
EOF
內容解密:
cat << EOF > /etc/ssmtp/ssmtp.conf:建立或覆寫/etc/ssmtp/ssmtp.conf檔案。- 各個組態項指定了SMTP伺服器的地址、埠、驗證資訊、TLS使用等。
對於實際的郵件投遞,可以使用公共或私有的郵件服務,如Google Mail SMTP、Sendgrid、Mailchimp或Amazon SES。也可以使用Sendy等工具簡化郵件傳送過程。