本文作者:知知行行 本文鏈接:https://www.cnblogs.com/loronoa/p/16566818.html docker容器網路 Docker在安裝後自動提供3種網路,可以使用docker network ls命令查看 [root@localhost ~]# docker netw ...
本文作者:知知行行
本文鏈接:https://www.cnblogs.com/loronoa/p/16566818.html
docker容器網路
Docker在安裝後自動提供3種網路,可以使用docker network ls命令查看
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
cd97bb997b84 bridge bridge local
0a04824fc9b6 host host local
4dcb8fbdb599 none null local
Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的預設網關。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通信。
docker的4種網路模式
網路模式 | 配置 | 說明 |
---|---|---|
host | --network host | 容器和宿主機共用Network namespace |
container | --network container:NAME_OR_ID | 容器和另外一個容器共用Network namespace |
none | --network none | 容器有獨立的Network namespace,但並沒有對其進行任何網路設置,如分配veth pair 和網橋連接,配置IP等 |
bridge | --network | bridge 預設模式 |
bridge模式
當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。
從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址為容器的預設網關。在主機上創建一對虛擬網卡veth pair設備,Docker將veth pair設備的一端放在新創建的容器中,並命名為eth0(容器的網卡),另一端放在主機中,以vethxxx這樣類似的名字命名,並將這個網路設備加入到docker0網橋中。可以通過brctl show命令查看。
bridge模式是docker的預設網路模式,不寫--network參數,就是bridge模式。使用docker run -p時,docker實際是在iptables做了DNAT規則,實現埠轉發功能。可以使用iptables -t nat -vnL查看。
bridge模式如下圖所示:
假設上圖的docker2中運行了一個nginx,大家來想幾個問題:
- 同主機間兩個容器間是否可以直接通信?比如在docker1上能不能直接訪問到docker2的nginx站點?
- 在宿主機上能否直接訪問到docker2的nginx站點?
- 在另一臺主機上如何訪問node1上的這個nginx站點呢?DNAT發佈?
Docker網橋是宿主機虛擬出來的,並不是真實存在的網路設備,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過映射容器埠到宿主主機(埠映射),即docker run創建容器時候通過 -p 或 -P 參數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。
container模式
這個模式指定新創建的容器和已經存在的一個容器共用一個 Network Namespace,而不是和宿主機共用。新創建的容器不會創建自己的網卡,配置自己的 IP,而是和一個指定的容器共用 IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。
container模式如下圖所示:
host模式
如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和埠。但是,容器的其他方面,如文件系統、進程列表等還是和宿主機隔離的。
使用host模式的容器可以直接使用宿主機的IP地址與外界通信,容器內部的服務埠也可以使用宿主機的埠,不需要進行NAT,host最大的優勢就是網路性能比較好,但是docker host上已經使用的埠就不能再用了,網路的隔離性不好。
Host模式如下圖所示:
none模式
使用none模式,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。需要我們自己為Docker容器添加網卡、配置IP等。
這種網路模式下容器只有lo迴環網路,沒有其他網卡。none模式可以在容器創建時通過--network none來指定。這種類型的網路沒有辦法聯網,封閉的網路能很好的保證容器的安全性。
應用場景:
- 啟動一個容器處理數據,比如轉換數據格式
- 一些後臺的計算和處理任務
none模式如下圖所示:
docker network inspect bridge #查看bridge網路的詳細配置
docker容器網路配置
Linux內核實現名稱空間的創建
ip netns命令
可以藉助ip netns命令來完成對 Network Namespace 的各種操作。ip netns命令來自於iproute安裝包,一般系統會預設安裝,如果沒有的話,請自行安裝。
註意:ip netns命令修改網路配置時需要 sudo 許可權。
可以通過ip netns命令完成對Network Namespace 的相關操作,可以通過ip netns help查看命令幫助信息:
[root@localhost ~]# ip netns help
Usage: ip netns list
ip netns add NAME
ip netns set NAME NETNSID
ip [-all] netns delete [NAME]
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd ...
ip netns monitor
ip netns list-id
預設情況下,Linux系統中是沒有任何 Network Namespace的,所以ip netns list命令不會返回任何信息。
創建Network Namespace
通過命令創建一個名為ns0的命名空間:
[root@localhost ~]# ip netns list
[root@localhost ~]# ip netns add ns0
[root@localhost ~]# ip netns list
ns0
新創建的 Network Namespace 會出現在/var/run/netns/目錄下。如果相同名字的 namespace 已經存在,命令會報Cannot create namespace file "/var/run/netns/ns0": File exists的錯誤。
[root@localhost ~]# ls /var/run/netns/
ns0
[root@localhost ~]# ip netns add ns0
Cannot create namespace file "/var/run/netns/ns0": File exists
對於每個 Network Namespace 來說,它會有自己獨立的網卡、路由表、ARP 表、iptables 等和網路相關的資源。
操作Network Namespace
ip命令提供了ip netns exec子命令可以在對應的 Network Namespace 中執行命令。
查看新創建 Network Namespace 的網卡信息
[root@localhost ~]# ip netns exec ns0 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
可以看到,新創建的Network Namespace中會預設創建一個lo迴環網卡,此時網卡處於關閉狀態。此時,嘗試去 ping 該lo迴環網卡,會提示Network is unreachable
[root@localhost ~]# ip netns exec ns0 ping 127.0.0.1
connect: Network is unreachable
127.0.0.1是預設迴環網卡
通過下麵的命令啟用lo迴環網卡:
[root@localhost ~]# ip netns exec ns0 ip link set lo up
[root@localhost ~]# ip netns exec ns0 ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.029 ms
^C
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1036ms
rtt min/avg/max/mdev = 0.029/0.029/0.029/0.000 ms
轉移設備
我們可以在不同的 Network Namespace 之間轉移設備(如veth)。由於一個設備只能屬於一個 Network Namespace ,所以轉移後在這個 Network Namespace 內就看不到這個設備了。
其中,veth設備屬於可轉移設備,而很多其它設備(如lo、vxlan、ppp、bridge等)是不可以轉移的。
veth pair
veth pair 全稱是 Virtual Ethernet Pair,是一個成對的埠,所有從這對埠一 端進入的數據包都將從另一端出來,反之也是一樣。
引入veth pair是為了在不同的 Network Namespace 直接進行通信,利用它可以直接將兩個 Network Namespace 連接起來。
創建veth pair
[root@localhost ~]# ip link add type veth
[root@localhost ~]# ip a
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 0a:f4:e2:2d:37:fb brd ff:ff:ff:ff:ff:ff
5: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 5e:7e:f6:59:f0:4f brd ff:ff:ff:ff:ff:ff
可以看到,此時系統中新增了一對veth pair,將veth0和veth1兩個虛擬網卡連接了起來,此時這對 veth pair 處於”未啟用“狀態。
實現Network Namespace間通信
下麵我們利用veth pair實現兩個不同的 Network Namespace 之間的通信。剛纔我們已經創建了一個名為ns0的 Network Namespace,下麵再創建一個信息Network Namespace,命名為ns1
[root@localhost ~]# ip netns add ns1
[root@localhost ~]# ip netns list
ns1
ns0
然後我們將veth0加入到ns0,將veth1加入到ns1
[root@localhost ~]# ip link set veth0 netns ns0
[root@localhost ~]# ip link set veth1 netns ns1
然後我們分別為這對veth pair配置上ip地址,並啟用它們
[root@localhost ~]# ip netns exec ns0 ip link set veth0 up
[root@localhost ~]# ip netns exec ns0 ip addr add 192.0.0.1/24 dev veth0
[root@localhost ~]# ip netns exec ns1 ip link set veth1 up
[root@localhost ~]# ip netns exec ns1 ip addr add 192.0.0.2/24 dev veth1
查看這對veth pair的狀態
[root@localhost ~]# ip netns exec ns0 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
4: veth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0a:f4:e2:2d:37:fb brd ff:ff:ff:ff:ff:ff link-netns ns1
inet 192.0.0.1/24 scope global veth0
valid_lft forever preferred_lft forever
inet6 fe80::8f4:e2ff:fe2d:37fb/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec ns1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: veth1@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 5e:7e:f6:59:f0:4f brd ff:ff:ff:ff:ff:ff link-netns ns0
inet 192.0.0.2/24 scope global veth1
valid_lft forever preferred_lft forever
inet6 fe80::5c7e:f6ff:fe59:f04f/64 scope link
valid_lft forever preferred_lft forever
從上面可以看出,我們已經成功啟用了這個veth pair,併為每個veth設備分配了對應的ip地址。我們嘗試在ns1中訪問ns0中的ip地址
[root@localhost ~]# ip netns exec ns1 ping 192.0.0.1
PING 192.0.0.1 (192.0.0.1) 56(84) bytes of data.
64 bytes from 192.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms
64 bytes from 192.0.0.1: icmp_seq=2 ttl=64 time=0.041 ms
^C
--- 192.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.033/0.037/0.041/0.004 ms
[root@localhost ~]# ip netns exec ns0 ping 192.0.0.2
PING 192.0.0.2 (192.0.0.2) 56(84) bytes of data.
64 bytes from 192.0.0.2: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 192.0.0.2: icmp_seq=2 ttl=64 time=0.025 ms
^C
--- 192.0.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1038ms
rtt min/avg/max/mdev = 0.025/0.025/0.025/0.000 ms
可以看到,veth pair成功實現了兩個不同Network Namespace之間的網路交互。
四種網路模式配置
bridge模式配置
[root@localhost ~]# docker run -it --name ti --rm busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1032 (1.0 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
在創建容器時添加--network bridge與不加--network選項效果是一致的
[root@localhost ~]# docker run -it --name t1 --network bridge --rm busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:696 (696.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
none模式配置
[root@localhost ~]# docker run -it --name t1 --network none --rm busybox
/ # ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
container模式配置
啟動第一個容器
[root@localhost ~]# docker run -dit --name b3 busybox
af5ba32f990ebf5a46d7ecaf1eec67f1712bbef6ad7df37d52b7a8a498a592a0
[root@localhost ~]# docker exec -it b3 /bin/sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:906 (906.0 B) TX bytes:0 (0.0 B)
啟動第二個容器
[root@localhost ~]# docker run -it --name b2 --rm busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516 (516.0 B) TX bytes:0 (0.0 B)
可以看到名為b2的容器IP地址是10.0.0.3,與第一個容器的IP地址不是一樣的,也就是說並沒有共用網路,此時如果我們將第二個容器的啟動方式改變一下,就可以使名為b2的容器IP與B3容器IP一致,也即共用IP,但不共用文件系統。
[root@localhost ~]# docker run -it --name b2 --rm --network container:b3 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1116 (1.0 KiB) TX bytes:0 (0.0 B)
此時我們在b1容器上創建一個目錄
/ # mkdir /tmp/data
/ # ls /tmp
data
到b2容器上檢查/tmp目錄會發現並沒有這個目錄,因為文件系統是處於隔離狀態,僅僅是共用了網路而已。
在b2容器上部署一個站點
/ # echo 'hello world' > /tmp/index.html
/ # ls /tmp
index.html
/ # httpd -h /tmp
/ # netstat -antl
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 :::80 :::* LISTEN
在b1容器上用本地地址去訪問此站點
/ # wget -O - -q 172.17.0.2:80
hello world
host模式配置
啟動容器時直接指明模式為host
[root@localhost ~]# docker run -it --name b2 --rm --network host busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:B8:7F:8E:2C
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:b8ff:fe7f:8e2c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:116 (116.0 B) TX bytes:1664 (1.6 KiB)
ens33 Link encap:Ethernet HWaddr 00:0C:29:95:19:47
inet addr:192.168.203.138 Bcast:192.168.203.255 Mask:255.255.255.0
inet6 addr: fe80::2e61:1ea3:c05a:3d9b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:9626 errors:0 dropped:0 overruns:0 frame:0
TX packets:3950 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3779562 (3.6 MiB) TX bytes:362386 (353.8 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
veth09ee47e Link encap:Ethernet HWaddr B2:10:53:7B:66:AE
inet6 addr: fe80::b010:53ff:fe7b:66ae/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:158 (158.0 B) TX bytes:1394 (1.3 KiB)
此時如果我們在這個容器中啟動一個http站點,我們就可以直接用宿主機的IP直接在瀏覽器中訪問這個容器中的站點了。
容器的常用操作
查看容器的主機名
[root@localhost ~]# docker run -it --name t1 --network bridge --rm busybox
/ # hostname
48cb45a0b2e7
在容器啟動時註入主機名
[root@localhost ~]# docker run -it --name t1 --network bridge --hostname ljl --rm busybox
/ # hostname
ljl
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 ljl
/ # cat /etc/resolv.conf
# Generated by NetworkManager
search localdomain
nameserver 192.168.203.2
/ # ping www.baidu.com
PING www.baidu.com (182.61.200.7): 56 data bytes
64 bytes from 182.61.200.7: seq=0 ttl=127 time=31.929 ms
64 bytes from 182.61.200.7: seq=1 ttl=127 time=41.062 ms
64 bytes from 182.61.200.7: seq=2 ttl=127 time=31.540 ms
^C
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 31.540/34.843/41.062 ms
手動指定容器要使用的DNS
[root@localhost ~]# docker run -it --name t1 --network bridge --hostname ljl --dns 114.114.114.114 --rm busybox
/ # cat /etc/resolv.conf
search localdomain
nameserver 114.114.114.114
/ # nslookup -type=a www.baidu.com
Server: 114.114.114.114
Address: 114.114.114.114:53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com
Name: www.a.shifen.com
Address: 182.61.200.6
Name: www.a.shifen.com
Address: 182.61.200.7
手動往/etc/hosts文件中註入主機名到IP地址的映射
[root@localhost ~]# docker run -it --name t1 --network bridge --hostname ljl --add-host www.a.com:1.1.1.1 --rm busybox
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
1.1.1.1 www.a.com
172.17.0.3 ljl
開放容器埠
執行docker run的時候有個-p選項,可以將容器中的應用埠映射到宿主機中,從而實現讓外部主機可以通過訪問宿主機的某埠來訪問容器內應用的目的。
-p選項能夠使用多次,其所能夠暴露的埠必須是容器確實在監聽的埠。
-p選項的使用格式:
- -p containerPort
- 將指定的容器埠映射至主機所有地址的一個動態埠
- -p hostPort : containerPort
- 將容器埠 containerPort 映射至指定的主機埠 hostPort
- -p ip :: containerPort
- 將指定的容器埠 containerPort 映射至主機指定 ip 的動態埠
- -p ip : hostPort : containerPort
- 將指定的容器埠 containerPort 映射至主機指定 ip 的埠 hostPort
動態埠指的是隨機埠,具體的映射結果可使用docker port命令查看。
[root@localhost ~]# docker run -dit --name web1 -p 192.168.203.138::80 httpd
e97bc1774e40132659990090f0e98a308a7f83986610ca89037713e9af8a6b9f
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e97bc1774e40 httpd "httpd-foreground" 6 seconds ago Up 5 seconds 192.168.203.138:49153->80/tcp web1
af5ba32f990e busybox "sh" 48 minutes ago Up 48 minutes b3
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 192.168.203.138:49153 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
以上命令執行後會一直占用著前端,我們新開一個終端連接來看一下容器的80埠被映射到了宿主機的什麼埠上
[root@localhost ~]# docker port web1
80/tcp -> 192.168.203.138:49153
由此可見,容器的80埠被暴露到了宿主機的49153埠上,此時我們在宿主機上訪問一下這個埠看是否能訪問到容器內的站點
[root@localhost ~]# curl http://192.168.203.138:49153
<html><body><h1>It works!</h1></body></html>
iptables防火牆規則將隨容器的創建自動生成,隨容器的刪除自動刪除規則。
[root@localhost ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
3 164 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
4 261 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.3 172.17.0.3 tcp dpt:80
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2 120 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
1 60 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
1 60 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.203.138 tcp dpt:49153 to:172.17.0.3:80
將容器埠映射到指定IP的隨機埠
[root@localhost ~]# docker run -dit --name web1 -p 192.168.203.138::80 httpd
在另一個終端上查看埠映射情況
[root@localhost ~]# docker port web1
80/tcp -> 192.168.203.138:49153
自定義docker0橋的網路屬性信息
自定義docker0橋的網路屬性信息需要修改/etc/docker/daemon.json配置文件
[root@localhost ~]# cd /etc/docker/
[root@localhost docker]# vim daemon.json
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker
{
"registry-mirrors": ["https://4hygggbu.mirror.aliyuncs.com/"],
"bip": "192.168.1.5/24"
}
EOF
[root@localhost ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
在客戶端上向dockerd直接傳遞“-H|--host”選項指定要控制哪台主機上的docker容器
[root@localhost ~]# docker -H 192.168.203.138:2375 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e97bc1774e40 httpd "httpd-foreground" 30 minutes ago Up 11 seconds 192.168.203.138:49153->80/tcp web1
af5ba32f990e busybox "sh" About an hour ago Up 14 seconds b3
創建新網路
[root@localhost ~]# docker network create ljl -d bridge
883eda50812bb214c04986ca110dbbcb7600eba8b033f2084cd4d750b0436e12
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
0c5f4f114c27 bridge bridge local
8c2d14f1fb82 host host local
883eda50812b ljl bridge local
85ed12d38815 none null local
創建一個額外的自定義橋,區別於docker0
[root@localhost ~]# docker network create -d bridge --subnet "192.168.2.0/24" --gateway "192.168.2.1" br0
af9ba80deb619de3167939ec5b6d6136a45dce90907695a5bc5ed4608d188b99
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
af9ba80deb61 br0 bridge local
0c5f4f114c27 bridge bridge local
8c2d14f1fb82 host host local
883eda50812b ljl bridge local
85ed12d38815 none null local
使用新創建的自定義橋來創建容器:
[root@localhost ~]# docker run -it --name b1 --network br0 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:02:02
inet addr:192.168.2.2 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:962 (962.0 B) TX bytes:0 (0.0 B)
再創建一個容器,使用預設的bridge橋:
[root@localhost ~]# docker run --name b2 -it busybox
/ # ls
bin dev etc home proc root sys tmp usr var
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:01:03
inet addr:192.168.1.3 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516 (516.0 B) TX bytes:0 (0.0 B)
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!