1. 程式人生 > 其它 >看了這麼多年西遊記,你可知道孫悟空是如何召喚土地公公的嗎?

看了這麼多年西遊記,你可知道孫悟空是如何召喚土地公公的嗎?

docker容器網路配置

ip netns(網路名稱空間)命令

[root@Aimmi ~]# rpm -qa|grep iproute
iproute-5.9.0-4.el8.x86_64
[root@Aimmi ~]# ip netns help
Usage:  ip netns list           // 列出所有的名稱空間
        ip netns add NAME       // 新增名稱空間
        ip netns attach NAME PID
        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 [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
NETNSID := auto | POSITIVE-INT

建立Network Namespace

通過命令建立一個名為ns0的名稱空間:
[root@Aimmi ~]# ip netns add ns0
[root@Aimmi ~]# ip netns list
ns0

通過命令刪除一個名為ns0的名稱空間:
[root@Aimmi ~]# ip netns delete ns0

如果相同名字的 namespace 已經存在,命令會報Cannot create namespace file “/var/run/netns/ns0”: File exists的錯誤。
[root@Aimmi ~]# ls /var/run/netns
ns0
[root@Aimmi ~]# ip netns add ns0
Cannot create namespace file "/var/run/netns/ns0": File exists


錯誤示範:手動建立一個名稱空間
[root@Aimmi ~]# touch /var/run/netns/ns1
[root@Aimmi ~]# ip netns list
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
ns1
ns0

對於每個 Network Namespace 來說,它會有自己獨立的網絡卡、路由表、ARP 表、iptables 等和網路相關的資源。

操作Network Namespace

p命令提供了ip netns exec子命令可以在對應的 Network Namespace 中執行命令。

檢視新建立 Network Namespace 的網絡卡資訊

[root@Aimmi ~]# ip netns exec ns0 ip a      進入ns0這個名稱空間裡面去執行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

可以看到,新建立的Network Namespace中會預設建立一個lo迴環網絡卡,此時網絡卡處於關閉狀態。此時,嘗試去 ping 該lo迴環網絡卡,會提示Network is unreachable

[root@Aimmi ~]# ip netns exec ns0 ping 127.0.0.1
connect: Network is unreachable

通過下面的命令啟用lo迴環網絡卡:

[root@Aimmi ~]# ip netns exec ns0 ip link set lo up
[root@Aimmi ~]# 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
[root@Aimmi ~]# 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.018 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.040 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.060 ms

轉移裝置

我們可以在不同的 Network Namespace 之間轉移裝置(如veth)。由於一個裝置只能屬於一個 Network Namespace ,所以轉移後在這個 Network Namespace 內就看不到這個裝置了。

其中,veth裝置屬於可轉移裝置,而很多其它裝置(如lo、vxlan、ppp、bridge等)是不可以轉移的。

容器一執行,veth就會自動出現
[root@Aimmi ~]# docker run -it --rm busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
3aab638df1a9: Pull complete 
Digest: sha256:52817dece4cfe26f581c834d27a8e1bcc82194f914afe6d50afad5a101234ef1
Status: Downloaded newer image for busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@Aimmi ~]# 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ff:ac:9f brd ff:ff:ff:ff:ff:ff
    inet 192.168.145.188/24 brd 192.168.145.255 scope global dynamic noprefixroute ens33
       valid_lft 1120sec preferred_lft 1120sec
    inet6 fe80::20c:29ff:feff:ac9f/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:78:55:12:e9 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:78ff:fe55:12e9/64 scope link 
       valid_lft forever preferred_lft forever
5: vethb2c2075@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
Error: Peer netns reference is invalid.
    link/ether 4a:47:02:f4:f0:d4 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::4847:2ff:fef4:f0d4/64 scope link 
       valid_lft forever preferred_lft forever                  //第五個

veth pair

veth pair 全稱是 Virtual Ethernet Pair,是一個成對的埠,所有從這對埠一 端進入的資料包都將從另一端出來,反之也是一樣。 引入veth pair是為了在不同的 Network Namespace 直接進行通訊,利用它可以直接將兩個 Network Namespace 連線起來。

建立veth pair

[root@Aimmi ~]# ip link add type veth
[root@Aimmi ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:ff:ac:9f brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 02:42:78:55:12:e9 brd ff:ff:ff:ff:ff:ff
6: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether e6:e0:e1:28:47:a6 brd ff:ff:ff:ff:ff:ff
7: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 7e:19:0b:08:a6:e5 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@Aimmi ~]# ip netns add ns1
[root@Aimmi ~]# ip netns list
ns1
ns0

然後我們將veth0加入到ns0,將veth1加入到ns1

[root@Aimmi ~]# ip link set veth0 netns ns0
[root@Aimmi ~]# 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
6: veth0@if7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether e6:e0:e1:28:47:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@Aimmi ~]# ip link set veth1 netns ns1
[root@Aimmi ~]# 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
7: veth1@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 7e:19:0b:08:a6:e5 brd ff:ff:ff:ff:ff:ff link-netns ns0

然後我們分別為這對veth pair配置上ip地址,並啟用它們

[root@Aimmi ~]# ip netns exec ns0 ip link set veth0 up
[root@Aimmi ~]# ip netns exec ns0 ip addr add 10.0.0.1/24 dev veth0
[root@Aimmi ~]# ip netns exec ns1 ip link set lo up
[root@Aimmi ~]# ip netns exec ns1 ip link set veth1 up
[root@Aimmi ~]# ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1

檢視這對veth pair的狀態

[root@Aimmi ~]# 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
6: veth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e6:e0:e1:28:47:a6 brd ff:ff:ff:ff:ff:ff link-netns ns1
    inet 10.0.0.1/24 scope global veth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e4e0:e1ff:fe28:47a6/64 scope link 
       valid_lft forever preferred_lft forever
[root@Aimmi ~]# ip netns exec ns1 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
7: veth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7e:19:0b:08:a6:e5 brd ff:ff:ff:ff:ff:ff link-netns ns0
    inet 10.0.0.2/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::7c19:bff:fe08:a6e5/64 scope link 
       valid_lft forever preferred_lft forever

從上面可以看出,我們已經成功啟用了這個veth pair,併為每個veth裝置分配了對應的ip地址。我們嘗試在ns1中訪問ns0中的ip地址:

[root@Aimmi ~]# ip netns exec ns1 ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.041 ms

veth裝置重新命名

[root@Aimmi ~]# ip netns exec ns0 ip link set veth0 down
[root@Aimmi ~]# ip netns exec ns0 ip link set dev veth0 name eth0
[root@Aimmi ~]# ip netns exec ns0 ip link set eth0 up
[root@Aimmi ~]# 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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e6:e0:e1:28:47:a6 brd ff:ff:ff:ff:ff:ff link-netns ns1
    inet 10.0.0.1/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e4e0:e1ff:fe28:47a6/64 scope link 
       valid_lft forever preferred_lft forever
[root@Aimmi ~]# ip netns exec ns1 ip link set veth1 down
[root@Aimmi ~]# ip netns exec ns1 ip link set dev veth1 name eth0
[root@Aimmi ~]# ip netns exec ns1 ip link set eth0 up
[root@Aimmi ~]# ip netns exec ns1 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
7: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7e:19:0b:08:a6:e5 brd ff:ff:ff:ff:ff:ff link-netns ns0
    inet 10.0.0.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::7c19:bff:fe08:a6e5/64 scope link 
       valid_lft forever preferred_lft forever
[root@Aimmi ~]# ip netns exec ns1 ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.027 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.080 ms

四種網路模式配置

bridge模式配置

[root@Aimmi ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # exit
[root@Aimmi ~]# docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

在建立容器時新增--network bridge與不加--network選項效果是一致的
[root@Aimmi ~]# docker run -it --rm --network bridge busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # exit

none模式配置

不用來通訊,只用來做一些簡單的操作

[root@Aimmi ~]# docker run -it --rm --network none busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
/ # exit

container模式配置

啟動第一個容器

[root@Aimmi ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

啟動第二個容器

[root@Aimmi ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

可以看到第二個容器的IP地址是172.17.0.3,與第一個容器的IP地址不是一樣的,也就是說並沒有共享網路,此時如果我們將第二個容器的啟動方式改變一下,就可以使第二個容器的IP與第一個容器的IP一致,也即共享IP,但不共享檔案系統。

前兩個不要退出 重新開個頁面

[root@Aimmi ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
bba83a5b7c03   busybox   "sh"      17 seconds ago   Up 16 seconds             thirsty_franklin
f9fc77e4709f   busybox   "sh"      4 minutes ago    Up 4 minutes              sharp_sanderson
[root@Aimmi ~]# docker run -it --rm --network container:f9fc77e4709f busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # hostname
f9fc77e4709f

此時我們在第一個容器上建立一個目錄

/ # mkdir /tmp/data
/ # ls /tmp
data

到第二個容器上檢查/tmp目錄會發現並沒有這個目錄,因為檔案系統是處於隔離狀態,僅僅是共享了網路而已。

/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var

在第二個容器上部署一個站點

 ls /var/www/
/ # echo 'test page' > /var/www/index.html
/ # /bin/httpd/ -f -h /var/www/
sh: /bin/httpd/: not found
/ # /bin/httpd -f -h /var/www/

[root@Aimmi ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
3342de98128c   busybox   "sh"      2 minutes ago   Up 2 minutes             wizardly_
brahmagupta
bba83a5b7c03   busybox   "sh"      4 minutes ago   Up 4 minutes             thirsty_f
ranklin
f9fc77e4709f   busybox   "sh"      7 minutes ago   Up 7 minutes             sharp_san
derson
[root@Aimmi ~]# docker exec -it 3342de98128c /bin/sh
/ # netstat -antl
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN   

在第一個容器上用本地地址去訪問此站點

/ # wget -O - -q 127.0.0.1
test page

由此可見,container模式下的容器間關係就相當於一臺主機上的兩個不同程序

host模式配置

啟動容器時直接指明模式為host

[root@Aimmi ~]# docker run -it --rm --network host busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel qlen 1000
    link/ether 00:0c:29:ff:ac:9f brd ff:ff:ff:ff:ff:ff
    inet 192.168.145.188/24 brd 192.168.145.255 scope global dynamic noprefixroute ens33
       valid_lft 968sec preferred_lft 968sec
    inet6 fe80::20c:29ff:feff:ac9f/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:78:55:12:e9 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:78ff:fe55:12e9/64 scope link 
       valid_lft forever preferred_lft forever
/ # ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel qlen 1000
    link/ether 00:0c:29:ff:ac:9f brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:78:55:12:e9 brd ff:ff:ff:ff:ff:ff

此時如果我們在這個容器中啟動一個http站點,我們就可以直接用宿主機的IP直接在瀏覽器中訪問這個容器中的站點了。

[root@Aimmi ~]# ss -antl
State           Recv-Q          Send-Q                    Local Address:Port                     Peer Address:Port          Process          
LISTEN          0               128                             0.0.0.0:22                            0.0.0.0:*                              
LISTEN          0               128                                [::]:22                               [::]:*    

/ # echo 'hello world' > /var/www/index.html
/ # /bin/httpd -f -h /var/www/
                          
[root@Aimmi ~]# ss -antl
State           Recv-Q          Send-Q                    Local Address:Port                     Peer Address:Port          Process          
LISTEN          0               128                             0.0.0.0:22                            0.0.0.0:*                              
LISTEN          0               128                                [::]:22                               [::]:*                              
LISTEN          0               9                                     *:80     

容器的常用操作

檢視容器的主機名

[root@Aimmi ~]# docker run -it --rm busybox
/ # hostname
1d183d992db1

在容器啟動時注入主機名

[root@Aimmi ~]# docker run -it --rm --hostname zs busybox
/ # hostname
zs
/ # cat /etc/hostname
zs
/ # 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.2      zs
/ # cat /etc/resolv.conf 
# Generated by NetworkManager
search localdomain
nameserver 192.168.145.2
/ # ping www.baidu.com
PING www.baidu.com (14.215.177.38): 56 data bytes
64 bytes from 14.215.177.38: seq=0 ttl=127 time=31.057 ms
64 bytes from 14.215.177.38: seq=1 ttl=127 time=39.754 ms
64 bytes from 14.215.177.38: seq=2 ttl=127 time=25.531 ms

手動指定容器要使用的DNS

[root@Aimmi ~]# docker run -it --rm --hostname zs --dns 114.114.114.114 busybox
/ # hostname
zs
/ # 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: 14.215.177.38
Name:   www.a.shifen.com
Address: 14.215.177.39

手動往/etc/hosts檔案中注入主機名到IP地址的對映

[root@Aimmi ~]# docker run -it --rm --hostname zs --dns 114.114.114.114 --add-host zs1:172.17.0.3 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
172.17.0.3      zs1
172.17.0.2      zs

開放容器埠

執行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命令檢視。

第一種 - p 的使用方式

[root@Aimmi ~]# docker run -d --name web --rm -p 80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
e5ae68f74026: Pull complete 
21e0df283cd6: Pull complete 
ed835de16acd: Pull complete 
881ff011f1c9: Pull complete 
77700c52c969: Pull complete 
44be98c0fab6: Pull complete 
Digest: sha256:9522864dd661dcadfd9958f9e0de192a1fdda2c162a35668ab6ac42b465f0603
Status: Downloaded newer image for nginx:latest
ed8bf7174213a1195fd8993b0d48a18817727d61a9be715f2fc431b92d35441e
[root@Aimmi ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                     NAMES
ed8bf7174213   nginx     "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   web

以上命令執行後會一直佔用著前端,我們新開一個終端連線來看一下容器的80埠被對映到了宿主機的什麼埠上

[root@Aimmi ~]# docker port web
80/tcp -> 0.0.0.0:49153
80/tcp -> :::49153

由此可見,容器的80埠被暴露到了宿主機的32769埠上,此時我們在宿主機上訪問一下這個埠看是否能訪問到容器內的站點

[root@Aimmi ~]# curl http://127.0.0.1:49153
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

第二種 - p 的方式:

將容器埠對映到宿主機的指定埠

[root@Aimmi ~]# docker run -d --name web --rm -p 80:80 nginx
ed8bf7174213a1195fd8993b0d48a18817727d61a9be715f2fc431b92d35441e
[root@Aimmi ~]# docker port web
80/tcp -> 0.0.0.0:80
80/tcp -> :::80

iptables防火牆規則將隨容器的建立自動生成,隨容器的刪除自動刪除規則。

第三種 - p 的方式:

將容器埠對映到指定IP的隨機埠

[root@Aimmi ~]# docker run --name web --rm -p 192.168.145.188::80 nginx

在另一個終端上檢視埠對映情況

[root@Aimmi ~]# docker port web
80/tcp -> 192.168.145.188:49153

第四種 - p 的方式:

將指定的容器埠對映至主機指定的埠

[root@Aimmi ~]# docker run -d --name web --rm -p 127.0.0.1:80:80 nginx
ed8bf7174213a1195fd8993b0d48a18817727d61a9be715f2fc431b92d35441e

在另一個終端上檢視埠對映情況

[root@Aimmi ~]# docker port web
80/tcp -> 127.0.0.1:80

自定義docker0橋的網路屬性資訊

自定義docker0橋的網路屬性資訊需要修改/etc/docker/daemon.json配置檔案

官方文件相關配置 https://docs.docker.com/network/bridge/

自定義docker0橋的網路屬性資訊需要修改/etc/docker/daemon.json配置檔案

[root@Aimmi ~]# vi /etc/docker/daemon.json 
{
    "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
    "big": "192.168.145.188"
}

[root@Aimmi ~]# systemctl restart docker
[root@Aimmi ~]# 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:a8:8f:68 brd ff:ff:ff:ff:ff:ff
    inet 192.168.47.161/24 brd 192.168.47.255 scope global noprefixroute dynamic ens33
       valid_lft 1169sec preferred_lft 1169sec
    inet6 fe80::c7db:4c9f:7bcc:55f5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:5b:66:73:8e brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:5bff:fe66:738e/64 scope link 
       valid_lft forever preferred_lft forever

核心選項為bip,即bridge ip之意,用於指定docker0橋自身的IP地址;其它選項可通過此地址計算得出。

docker遠端連線(不常用)

dockerd守護程序的C/S,其預設僅監聽Unix Socket格式的地址(/var/run/docker.sock),如果要使用TCP套接字,則需要修改/etc/docker/daemon.json配置檔案

docker建立自定義橋

建立一個額外的自定義橋,區別於docker0

[root@Aimmi ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
bfef3a5a370d   bridge    bridge    local
6ceb6009fa51   host      host      local
722f6ab96f26   none      null      local
[root@Aimmi ~]# docker network create -d bridge --subnet "192.168.2.0/24" --gateway "192.168.2.1" br0
a298744eb8b168ee11c122a301dfd44d699c9cca7bfb9177944aae51fa7cef0e
[root@Aimmi ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a298744eb8b1   br0       bridge    local
bfef3a5a370d   bridge    bridge    local
6ceb6009fa51   host      host      local
722f6ab96f26   none      null      local

使用新建立的自定義橋來建立容器:

[root@Aimmi ~]# docker run -it --rm --network br0 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:a8:02:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0
       valid_lft forever preferred_lft forever

再建立一個容器,使用預設的bridge橋:

[root@Aimmi ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

試想一下,此時的b2與b1能否互相通訊?如果不能該如何實現通訊?

/ # hostname
1d183d992db1

[root@Aimmi ~]# docker network connect br0 bb1a030ba094 1d183d992db1

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
27: eth1@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:a8:02:03 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.3/24 brd 192.168.2.255 scope global eth1
       valid_lft forever preferred_lft forever
/ # ping 192.168.2.2
PING 192.168.2.2 (192.168.2.2): 56 data bytes
64 bytes from 192.168.2.2: seq=0 ttl=64 time=0.204 ms
64 bytes from 192.168.2.2: seq=1 ttl=64 time=0.069 ms
64 bytes from 192.168.2.2: seq=2 ttl=64 time=0.079 ms