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 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]

默认情况下,Linux系统中是没有任何 Network Namespace的,所以ip netns list命令不会返回任何信息。

创建Network Namespace

通过命令创建一个名为ns1的命名空间:

[root@localhost ~]# ip netns list
[root@localhost ~]# ip netns add ns1
[root@localhost ~]# ip netns list
ns1

新创建的 Network Namespace 会出现在/var/run/netns/目录下。如果相同名字的 namespace 已经存在,命令会报Cannot create namespace file “/var/run/netns/ns1”: File exists的错误。

[root@localhost ~]# ls /var/run/netns/
ns1
[root@localhost ~]# ip netns add ns1
Cannot create namespace file "/var/run/netns/ns1": File exists

对于每个 Network Namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。

操作Network Namespace

ip命令提供了ip netns exec子命令可以在对应的 Network Namespace 中执行命令。

查看新创建 Network Namespace 的网卡信息

[root@localhost ~]# ip netns exec ns1 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 ns1 ping 127.0.0.1
connect: 网络不可达

通过下面的命令启用lo回环网卡:

[root@localhost ~]# ip netns exec ns1 ip link set lo up
[root@localhost ~]# ip netns exec ns1 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.032 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.028 ms
^C
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2056ms
rtt min/avg/max/mdev = 0.028/0.036/0.050/0.011 ms

[root@localhost ~]# ip netns exec ns1 ip addr
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

转移设备
我们可以在不同的 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 连接起来。

net core docker 连接sql server 2008 ssl docker net is_网络


创建veth pair

[root@localhost ~]# ip link add type veth
[root@localhost ~]# 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:cc:68:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.134/24 brd 192.168.71.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::b0aa:5d3b:1352:b7cb/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 07:42:51:41:82:fc 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
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether aa:08:34:bd:2f:36 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 f6:96:64:4e:59:d2 brd ff:ff:ff:ff:ff:ff

可以看到,此时系统中新增了一对veth pair,将veth0和veth1两个虚拟网卡连接了起来,此时这对 veth pair 处于”未启用“状态。

实现Network Namespace间通信

下面利用veth pair实现两个不同的 Network Namespace 之间的通信,刚才已经创建了一个名为ns1的 Network Namespace,下面再创建一个信息Network Namespace,命名为ns2

[root@localhost ~]# ip netns add ns2
[root@localhost ~]# ip netns list
ns1
ns2

然后我们将veth0加入到ns1,将veth1加入到ns2

[root@localhost ~]# ip link set veth0 netns ns1
[root@localhost ~]# ip link set veth1 netns ns2

然后我们分别为这对veth pair配置上ip地址,并启用它们

[root@localhost ~]# ip netns exec ns1 ip link set veth0 up
[root@localhost ~]# ip netns exec ns1 ip addr add 192.168.71.134/24 dev veth0
[root@localhost ~]# ip netns exec ns2 ip link set lo up
[root@localhost ~]# ip netns exec ns2 ip link set veth1 up
[root@localhost ~]# ip netns exec ns2 ip addr add 192.168.71.138/24 dev veth1

查看这对veth pair的状态

//ns1
[root@localhost ~]# 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
4: veth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether aa:07:34:bd:2f:36 brd ff:ff:ff:ff:ff:ff link-netns ns2
    inet 192.168.71.134/24 scope global veth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a807:34ff:febd:2f36/64 scope link 
       valid_lft forever preferred_lft forever

//ns2
[root@localhost ~]# ip netns exec ns2 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
5: veth1@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether f6:96:64:4e:59:d2 brd ff:ff:ff:ff:ff:ff link-netns ns1
    inet 192.168.71.138/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::f496:64ff:fe4e:59d2/64 scope link 
       valid_lft forever preferred_lft forever

从上面可以看出,我们已经成功启用了这个veth pair,并为每个veth设备分配了对应的ip地址。我们尝试在ns2中访问ns1中的ip地址:

[root@localhost ~]# ip netns  exec lq1 ping 192.168.71.134
PING 192.168.71.134 (192.168.71.134) 56(84) bytes of data.
64 bytes from 192.168.71.134: icmp_seq=1 ttl=64 time=0.040 ms
64 bytes from 192.168.71.134: icmp_seq=2 ttl=64 time=0.032 ms
^C
--- 192.168.71.134 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1048ms
rtt min/avg/max/mdev = 0.032/0.036/0.040/0.004 ms

可以看到,veth pair成功实现了两个不同Network Namespace之间的网络交互。
veth设备重命名

[root@localhost ~]# ip netns exec ns1 ip link set veth0 down
[root@localhost ~]# ip netns exec ns2 ip link set dev veth0 name eth0

##需要安装ifconfig才可以使用该命令
[root@localhost ~]# yum -y install net-tools
[root@localhost ~]# ip netns exec lq0 ifconfig -a
eth0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.71.134  netmask 255.255.255.0  broadcast 0.0.0.0
        ether aa:07:34:bd:2f:36  txqueuelen 1000  (Ethernet)
        RX packets 19  bytes 1426 (1.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 19  bytes 1426 (1.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 6  bytes 504 (504.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6  bytes 504 (504.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

四种网络模式配置

bridge模式配置

[root@localhost ~]# docker run -it --name test1 --rm centos
[root@81876c60c189 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 1905  bytes 12696429 (12.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1420  bytes 81744 (79.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
## 在创建容器时添加--network bridge与不加--network选项效果是一致的
[root@localhost ~]# docker run -it --name test1 --network bridge --rm centos
[root@a791be8ff1ed /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 2083  bytes 14602033 (13.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1659  bytes 96478 (94.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

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 -it --name test1 --rm centos
[root@461f4cb58c9c /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 1991  bytes 12700989 (12.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1571  bytes 89898 (87.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

启动第二个容器

[root@localhost ~]# docker run -it --name test2 --rm centos
[root@8d4e2eb289d2 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
        RX packets 1567  bytes 12678005 (12.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1340  bytes 77424 (75.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

可以看到第二个的容器IP地址是172.17.0.3,与第一个容器的IP地址不是一样的,也就是说并没有共享网络,此时如果我们将第二个容器的启动方式改变一下,就可以使第二个的容器IP与第一个容器IP一致,也即共享IP,但不共享文件系统。

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
461f4cb58c9c   centos    "/bin/bash"   4 minutes ago   Up 4 minutes             test1
[root@localhost ~]# docker run -it --name test2 --network container:test1 --rm centos

[root@461f4cb58c9c /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 5044  bytes 30513598 (29.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4106  bytes 238432 (232.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
//此时我们在test1容器上创建一个目录

[root@461f4cb58c9c opt]# mkdir test
[root@461f4cb58c9c opt]# ls
test

//到test2容器上检查/opt目录会发现并没有这个目录,因为文件系统是处于隔离状态,仅仅是共享了网络而已

[root@461f4cb58c9c opt]# ls
[root@461f4cb58c9c opt]# 

//到test2容器上检查/opt目录会发现并没有这个目录,因为文件系统是处于隔离状态,仅仅是共享了网络而已

//在test2容器上部署一个站点
[root@461f4cb58c9c ~]# echo "me httpd" > www/index.html
[root@461f4cb58c9c ~]# httpd -h www/
[root@461f4cb58c9c ~]# netstat -antl
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTE

//在test1上访问
[root@461f4cb58c9c ~]# curl 172.17.0.2
me httpd
[root@461f4cb58c9c ~]#
# 由此可见,container模式下的容器间关系就相当于一台主机上的两个不同进程

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

host模式配置

启动容器时直接指明模式为host

[root@localhost ~]# docker run -it --name t1 --network host --rm centos
[root@localhost /]# 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:cc:68:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.139/24 brd 192.168.71.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::b0aa:5d3b:1352:b7cb/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 09:13:51:41:82:fc 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:51ff:fe41:82fc/64 scope link 
       valid_lft forever preferred_lft forever
容器的常用操作

查看容器的主机名

[root@localhost ~]# docker run -it --name test1 --rm centos
[root@abb020e4587f /]# hostname
abb020e4587f

在容器启动时注入主机名

[root@localhost ~]# docker run -it --name test1 --hostname lql --rm centos
[root@lql /]# hostname
lql

[root@lql /]# 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      lql # 注入主机名时会自动创建主机名到IP的映射关系

[root@lql /]# cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 8.8.8.8 # DNS也会自动配置为宿主机的DNS
[root@lql /]# ping baidu.com
PING baidu.com (220.181.38.251) 56(84) bytes of data.
64 bytes from 220.181.38.251 (220.181.38.251): icmp_seq=1 ttl=127 time=111 ms
64 bytes from 220.181.38.251 (220.181.38.251): icmp_seq=2 ttl=127 time=144 ms

手动指定容器要使用的DNS

[root@localhost ~]# docker run -it --name test1 --hostname lql --dns 114.114.114.114 --rm centos
[root@lql /]# cat /etc/resolv.conf 
nameserver 114.114.114.114

手动往/etc/hosts文件中注入主机名到IP地址的映射

[root@localhost ~]# docker run -it --name test1 --hostname lql --add-host www.liu.com:110.110.110.110 --rm centos
[root@lql /]# 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
110.110.110.110 www.test.com
172.17.0.2      lql
开放容器端口

执行docker run的时候有个-p选项,可以将容器中的应用端口映射到宿主机中,从而实现让外部主机可以通过访问宿主机的某端口来访问容器内应用的目的。

-p选项能够使用多次,其所能够暴露的端口必须是容器确实在监听的端口。

-p选项的使用格式:

-p <containerPort>
将指定的容器端口映射至主机所有地址的一个动态端口
-p <hostPort>:<containerPort>
将容器端口<containerPort>映射至指定的主机端口<hostPort>
-p <ip>::<containerPort>
将指定的容器端口<containerPort>映射至主机指定<ip>的动态端口
-p <ip>::<containerPort>
将指定的容器端口<containerPort>映射至主机指定<ip>的端口<hostPort>
动态端口指的是随机端口,具体的映射结果可使用docker port命令查看。

[root@localhost ~]# docker run -d --name test --rm -p 80 best2001/nginx:v0.3
681e2161bdad77d2ef7b1937faf22f2f1082b4bf0874a1188c5a3b4f3e73a1b7

以上命令执行后会一直占用着前端,我们新开一个终端连接来看一下容器的80端口被映射到了宿主机的什么端口上

[root@localhost ~]# docker port test
80/tcp -> 0.0.0.0:49154
80/tcp -> :::49154

由此可见,容器的80端口被暴露到了宿主机的32769端口上,此时我们在宿主机上访问一下这个端口看是否能访问到容器内的站点

[root@localhost ~]# curl 192.168.71.139:49154
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    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>

iptables防火墙规则将随容器的创建自动生成,随容器的删除自动删除规则。

将容器端口映射到指定IP的随机端口

[root@localhost ~]# docker run -d --name test --rm -p 192.168.71.139::80 best2001/nginx:v0.3
defa708d33058efde55145fc85cd2c64a3c2f3c6ce3b9e83a6566953dfab61a2
[root@localhost ~]# docker port test
80/tcp -> 192.168.71.139:49153

将容器端口映射到宿主机的指定端口

[root@localhost ~]# docker run -d --name test --rm -p 80:80 best2001/nginx:v0.3
fdcd5347cc2f3ed31ba8d6ba0f46661acbb4a7dc2aa397a2758abc87360d1559
[root@localhost ~]# docker port test
80/tcp -> 0.0.0.0:80
80/tcp -> :::80
自定义docker0桥的网络属性信息

参考官方文档 自定义docker0桥的网络属性信息需要修改/etc/docker/daemon.json配置文件

[root@localhost ~]# vim /etc/docker/daemon.json 
[root@localhost ~]# cat /etc/docker/daemon.json 
{
    "registry-mirrors": ["https://wn5c7d7w.mirror.aliyuncs.com/"],
    "bip": "192.168.2.1/24"  ## 改变宿主机的docker0网卡IP
}

[root@localhost ~]# systemctl restart docker

[root@localhost ~]# 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:cc:68:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.139/24 brd 192.168.71.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::b0aa:5d3b:1352:b7cb/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 09:12:51:41:82:fc brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.1/24 brd 192.168.2.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:51ff:fe41:82fc/64 scope link 
       valid_lft forever preferred_lft forever

核心选项为bip,即bridge ip之意,用于指定docker0桥自身的IP地址;其它选项可通过此地址计算得出。

docker创建自定义桥

创建一个额外的自定义桥,区别于docker0

[root@localhost ~]# docker network create -d bridge --subnet "172.17.2.0/24" --gateway "172.17.2.1" br0
6c81564402952e69ffe6fd1735fa94790d58c3d58f6a426ffb1d47b53b8d3e4b
[root@localhost ~]# 
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
6c8156440295   br0       bridge    local
0c4dfc56dda3   bridge    bridge    local
775ddefd7576   host      host      local
9e8ab03a1af5   none      null      local

使用新创建的自定义桥来创建容器:

[root@localhost ~]# docker run -it --name test --rm --network br0 centos

[root@8bcfbcefbc48 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.2.2  netmask 255.255.255.0  broadcast 172.17.2.255
        ether 02:42:ac:11:02:02  txqueuelen 0  (Ethernet)
        RX packets 1868  bytes 12694425 (12.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1470  bytes 84444 (82.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 64  bytes 5516 (5.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 64  bytes 5516 (5.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

再创建一个容器,使用默认的bridge桥

[root@localhost ~]# docker run -it --name test2 --rm  centos

[root@0ac299077b3c /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.2  netmask 255.255.255.0  broadcast 192.168.2.255
        ether 02:42:c0:a8:02:02  txqueuelen 0  (Ethernet)
        RX packets 1970  bytes 12699829 (12.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1532  bytes 87812 (85.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

test与test2实现通信

net core docker 连接sql server 2008 ssl docker net is_docker_02


test

[root@localhost ~]# docker run -it --name test --rm --network br0 best2001/nginx:v0.3 /bin/bash
[root@00172f85f3ea /]#
[root@00172f85f3ea /]# 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
41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:02:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.2.2/24 brd 172.17.2.255 scope global eth0
       valid_lft forever preferred_lft forever

test2

[root@localhost ~]# docker run -it --name test2 --rm best2001/nginx:v0.3 /bin/bash
[root@02ca5fa59566 /]# 
[root@02ca5fa59566 /]# 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
45: eth0@if46: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c0:a8:02:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0
       valid_lft forever preferred_lft forever

将br0网络test连接到test2,一个容器运行两个桥

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND       CREATED         STATUS         PORTS     NAMES
02ca5fa59566   best2001/nginx:v0.3   "/bin/bash"   2 minutes ago   Up 2 minutes             test2
00172f85f3ea   best2001/nginx:v0.3   "/bin/bash"   3 minutes ago   Up 3 minutes             test
[root@localhost ~]# docker network connet br0 02ca5fa59566

test2查看并ping test

[root@02ca5fa59566 /]# 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
45: eth0@if46: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 09:42:c0:a8:02:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0
       valid_lft forever preferred_lft forever
47: eth1@if48: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:02:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.2.3/24 brd 172.17.2.255 scope global eth1
       valid_lft forever preferred_lft forever
       
[root@02ca5fa59566 /]# ping 127.17.2.2
PING 127.17.2.2 (127.17.2.2) 56(84) bytes of data.
64 bytes from 127.17.2.2: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 127.17.2.2: icmp_seq=2 ttl=64 time=0.026 ms
64 bytes from 127.17.2.2: icmp_seq=3 ttl=64 time=0.027 ms
^C
--- 127.17.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2046ms
rtt min/avg/max/mdev = 0.026/0.030/0.037/0.005 ms