docker容器网络配置

Linux内核实现名称空间的创建

ip netns命令

可以借助ip netns命令来完成对 Network Namespace 的各种操作。ip netns命令来自于iproute安装包,一般系统会默认安装,如果没有的话,请自行安装。

注意:ip netns命令修改网络配置时需要 sudo 权限。

可以通过ip netns命令完成对Network Namespace 的相关操作,可以通过ip netns help查看命令帮助信息:

 1 [root@localhost ~]# ip netns help     2 Usage:    ip netns list      #    查看名称空间  3     ip netns add NAME    #  添加名称空间  4     ip netns attach NAME PID   #   进到空间里去  5     ip netns set NAME NETNSID   #   设置名称空间的名字  6     ip [-all] netns delete [NAME]   # 删除    7     ip netns identify [PID]  8     ip netns pids NAME     #    pid  9     ip [-all] netns exec [NAME] cmd ...   #   进到空间去并执行命令 10     ip netns monitor       #   监控 11     ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT] 12 NETNSID := auto | POSITIVE-INT    #   列出id

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

创建Network Namespace

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

1 [root@localhost ~]# ip netns add ns0    #   创建一个叫ns0的名称空间 2 [root@localhost ~]# ip netns list        #    查看 3 ns0

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

 1 [root@localhost ~]# cd /var/run/netns/    #  进到存放名称空间的目录  2 [root@localhost netns]# ls  3 ns0  4 [root@localhost ~]# file /var/run/netns/      5 /var/run/netns/: directory  6 [root@localhost ~]# file /var/run/netns/ns0   7 /var/run/netns/ns0: empty  8 [root@localhost ~]# touch /var/run/netns/ns1    9 [root@localhost ~]# file /var/run/netns/ns1 10 /var/run/netns/ns1: empty        #  touch出来的,看着都一样 11 [root@localhost ~]# ip netns list    #  但是你查看就会报错 12 Error: Peer netns reference is invalid. 13 Error: Peer netns reference is invalid.      #  必须要用命令创建, 14 ns1 15 ns0 16 [root@localhost ~]# ip netns add ns0     #  不能创建相同名字,会报错 17 Cannot create namespace file /var/run/netns/ns0: File exists

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

操作Network Namespace

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

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

1 [root@localhost ~]# ip netns exec ns0 ip a   #  进到ns0查看网络信息 2 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000    #   就一块lo网卡,而且没有激活 3     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

可以看到,新创建的Network Namespace中会默认创建一个lo回环网卡,此时网卡处于关闭状态。此时,尝试去 ping 该lo回环网卡,会提示Network is unreachable

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

 1 [root@localhost ~]# ip netns exec ns0 ping 127.0.0.1    #  进到ns0,ping自己   2 connect: 网络不可达    3 [root@localhost ~]# ip netns exec ns0 ip link set lo up   #  进到ns0设置lo网卡启动  4 [root@localhost ~]# ip netns exec ns0 ip a  5 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000  6     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  7     inet 127.0.0.1/8 scope host lo    #  有id了激活了  8        valid_lft forever preferred_lft forever  9     inet6 ::1/128 scope host  10        valid_lft forever preferred_lft forever 11 [root@localhost ~]# ip netns exec ns0 ping 127.0.0.1   #  此时就ping的通 12 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 13 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=40.5 ms 14 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.062 ms 15 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.095 ms 16

    [root@localhost ~]# ip netns exec ns1 ip link set lo up   # 激活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              #  两个空间的本地网络通了,他们两个之间是不能通信的真机也不能和他们通信,内部是可以通信的,

转移设备

我们可以在不同的 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

 1 [root@localhost ~]#  ip link show     #  此时只有3个网卡  2 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000  3     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  4 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000  5     link/ether 00:0c:29:bc:11:bf brd ff:ff:ff:ff:ff:ff  6 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default   7     link/ether 02:42:e7:69:ef:af brd ff:ff:ff:ff:ff:ff  8 [root@localhost ~]# ip link add type veth   #  生产了一对设备38: veth0   39: veth1而且是没有激活的状态  9 [root@localhost ~]# ip link show 10 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 11     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 12 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 13     link/ether 00:0c:29:bc:11:bf brd ff:ff:ff:ff:ff:ff 14 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default  15     link/ether 02:42:e7:69:ef:af brd ff:ff:ff:ff:ff:ff 16 38: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 17     link/ether d2:62:7c:c0:44:7f brd ff:ff:ff:ff:ff:ff 18 39: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 19     link/ether 7e:b1:dd:27:56:87 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

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

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

查看这对veth pair的状态

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

 1 [root@localhost ~]# ip link set veth0 netns ns0   # 把veth0给ns0用  2 [root@localhost ~]# ip netns exec ns0 ip a    3 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000  4     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  5     inet 127.0.0.1/8 scope host lo  6        valid_lft forever preferred_lft forever  7     inet6 ::1/128 scope host   8        valid_lft forever preferred_lft forever  9 38: veth0@if39: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 10     link/ether d2:62:7c:c0:44:7f brd ff:ff:ff:ff:ff:ff link-netnsid 0 11 [root@localhost ~]# ip netns exec ns0 ip link set veth0 up  #  激活veth0 12 [root@localhost ~]# ip netns exec ns0 ip a    #  此时已激活但是没有ip 13 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 14     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 15     inet 127.0.0.1/8 scope host lo 16        valid_lft forever preferred_lft forever 17     inet6 ::1/128 scope host  18        valid_lft forever preferred_lft forever 19 38: veth0@if39: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000 20     link/ether d2:62:7c:c0:44:7f brd ff:ff:ff:ff:ff:ff link-netnsid 0 21 [root@localhost ~]# ip netns exec ns0 ip addr add 1.1.1.1/24 dev veth0    #   给veth0手动配一个ip 22 [root@localhost ~]# ip netns exec ns0 ip a 23 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 24     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 25     inet 127.0.0.1/8 scope host lo 26        valid_lft forever preferred_lft forever 27     inet6 ::1/128 scope host  28        valid_lft forever preferred_lft forever 29 38: veth0@if39: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000 30     link/ether d2:62:7c:c0:44:7f brd ff:ff:ff:ff:ff:ff link-netnsid 0 31     inet 1.1.1.1/24 scope global veth0     #此时已经有ip 32        valid_lft forever preferred_lft forever 33 [root@localhost ~]# ip link show    #  把veht0给了ns0,所以真机这里就没有了 34 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 35     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 36 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 37     link/ether 00:0c:29:bc:11:bf brd ff:ff:ff:ff:ff:ff 38 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default  39     link/ether 02:42:e7:69:ef:af brd ff:ff:ff:ff:ff:ff 40 39: veth1@if38: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 41     link/ether 7e:b1:dd:27:56:87 brd ff:ff:ff:ff:ff:ff link-netns ns0 42 [root@localhost ~]# ip link set veth1 up  #  激活veth1 43 [root@localhost ~]# ip addr add 1.1.1.2/24 dev veth1  #   给veth1设置ip 44 [root@localhost ~]# ping 1.1.1.1   #   ping的通 45 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 46 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=17.3 ms 47 64 bytes from 1.1.1.1: icmp_seq=2 ttl=64 time=0.057 ms 48 [root@localhost ~]# ip link set veth1 netns ns1   #  把veth1给ns1用 49 [root@localhost ~]# ip netns exec ns1 ip a 50 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 51     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 52     inet 127.0.0.1/8 scope host lo 53        valid_lft forever preferred_lft forever 54     inet6 ::1/128 scope host  55        valid_lft forever preferred_lft forever 56 39: veth1@if38: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000   #  移过的时候会禁用掉,ip也没了 57     link/ether 7e:b1:dd:27:56:87 brd ff:ff:ff:ff:ff:ff link-netns ns0 58  [root@localhost ~]# ip netns exec ns1 ip link set veth1 up  #  启动veth1 59 [root@localhost ~]# ip netns exec ns1 ip addr add 1.1.1.2/24 dev veth1    #   给veth1配置ip 60 [root@localhost ~]# ip netns exec ns1 ip a 61 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 62     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 63     inet 127.0.0.1/8 scope host lo 64        valid_lft forever preferred_lft forever 65     inet6 ::1/128 scope host  66        valid_lft forever preferred_lft forever 67 39: veth1@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 68     link/ether 7e:b1:dd:27:56:87 brd ff:ff:ff:ff:ff:ff link-netns ns0 69     inet 1.1.1.2/24 scope global veth1    #  此时veth有ip了 70        valid_lft forever preferred_lft forever 71     inet6 fe80::7cb1:ddff:fe27:5687/64 scope link  72        valid_lft forever preferred_lft forever 73 [root@localhost ~]# ip netns exec ns1 ping 1.1.1.1   #  进到ns1,去ping1.1.1.1,能通说明ns1和ns0可以通信 74 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 75 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=6.30 ms 76 64 bytes from 1.1.1.1: icmp_seq=2 ttl=64 time=0.076 ms 77 64 bytes from 1.1.1.1: icmp_seq=3 ttl=64 time=0.077 ms

veth设备重命名

 1 [root@localhost ~]# ip netns exec ns0 ip link show   #  两个veth的设备名字不一样  2 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000  3     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  4 38: veth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000  5     link/ether d2:62:7c:c0:44:7f brd ff:ff:ff:ff:ff:ff link-netns ns1  6 [root@localhost ~]# ip netns exec ns1 ip link show  7 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000  8     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  9 39: veth1@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 10     link/ether 7e:b1:dd:27:56:87 brd ff:ff:ff:ff:ff:ff link-netns ns0 11 [root@localhost ~]# ip netns exec ns0 ip link set veth0 down   #  停掉veth0  才能操作改名 12 [root@localhost ~]# ip netns exec ns0 ip link set dev veth0 name eth0    #   把veth0的名字改成eth0 13 [root@localhost ~]# ip netns exec ns0 ip link set eth0 up   #  启动eth0 14 [root@localhost ~]# ip netns exec ns1 ip link set veth1  down  #  停掉veth1 15 [root@localhost ~]# ip netns exec ns1 ip link set dev veth1 name eth0   # 把veth1的名字改成eth0 16 [root@localhost ~]# ip netns exec ns1 ip link set eth0 up    # 启动 17 [root@localhost ~]# ip netns exec ns1 ping 1.1.1.1    # 也能通 18 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 19 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.121 ms 20 64 bytes from 1.1.1.1: icmp_seq=2 ttl=64 time=0.103 ms 21 64 bytes from 1.1.1.1: icmp_seq=3 ttl=64 time=0.067 ms 22      #    改名字不会影响设置的ip,但是需要先停掉,改好再启动。容器会自动分配ip,并且和docker0网桥在同一个网段,会虚拟一对veth设备一个放在容器,一个放在我们的真机上。 23  24     

四种网络模式配置

bridge模式配置(桥接模式)

 1 [root@localhost ~]# docker run -it --rm busybox    # 桥接是默认的,不用network也可以  2 / # ifconfig   3 eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02    4           inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0  5           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1  6           RX packets:9 errors:0 dropped:0 overruns:0 frame:0  7           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0  8           collisions:0 txqueuelen:0   9           RX bytes:806 (806.0 B)  TX bytes:0 (0.0 B) 10  11 lo        Link encap:Local Loopback   12           inet addr:127.0.0.1  Mask:255.0.0.0 13           UP LOOPBACK RUNNING  MTU:65536  Metric:1 14           RX packets:0 errors:0 dropped:0 overruns:0 frame:0 15           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 16           collisions:0 txqueuelen:1000  17           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B) 18 [root@localhost ~]# docker run -it --network bridge busybox 19 / # ifconfig  20 eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02   21           inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0 22           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1 23           RX packets:10 errors:0 dropped:0 overruns:0 frame:0 24           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 25           collisions:0 txqueuelen:0  26           RX bytes:876 (876.0 B)  TX bytes:0 (0.0 B) 27  28 lo        Link encap:Local Loopback   29           inet addr:127.0.0.1  Mask:255.0.0.0 30           UP LOOPBACK RUNNING  MTU:65536  Metric:1 31           RX packets:0 errors:0 dropped:0 overruns:0 frame:0 32           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 33           collisions:0 txqueuelen:1000  34           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

none模式配置(孤岛模式)

[root@localhost ~]# docker run -it --rm --network none busybox / # ifconfig  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模式就只有一块lo网卡,没有其他网卡和ip,无法和外界通信

container模式配置 (容器模式)

启动第一个容器

 1 [root@localhost ~]# docker run -it --rm --name b1 busybox    2 / # ip a  3 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000  4     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  5     inet 127.0.0.1/8 scope host lo  6        valid_lft forever preferred_lft forever  7 50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue   8     link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff  9     inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 10        valid_lft forever preferred_lft forever 11 #   先启动一个正常的容器取名b1,然后在启动一个容器指定容器模式 12 和b1一样。 13 [root@localhost ~]# docker run -it --rm --network container:b1 busybox 14 / # ip a 15 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 16     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 17     inet 127.0.0.1/8 scope host lo 18        valid_lft forever preferred_lft forever 19 50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue  20     link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff 21     inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 22        valid_lft forever preferred_lft forever
 1 没有名字的容器下面创建一个data目录  2 / # ls  3 bin   dev   etc   home  proc  root  sys   tmp   usr   var  4 / # mkdir data  5 / # ls  6 bin   data  dev   etc   home  proc  root  sys   tmp   usr   var  7 / #   8 b1容器查看不到  9 / # ls 10 bin   dev   etc   home  proc  root  sys   tmp   usr   var 11 共享IP,但不共享文件系统,因为文件系统是处于隔离状态,仅仅是共享了网络而已 12 / # echo 'hello world' > data/index.html   #  没有名字的容器里再跑一个容器 13 / # /bin/httpd -h /data 14 / # netstat -antl 15 Active Internet connections (servers and established) 16 Proto Recv-Q Send-Q Local Address           Foreign Address         State        17 tcp        0      0 :::80                   :::*                    LISTEN       18 / # wget -O - -q 127.0.0.1  # b1可以访问到,应为他们用的是同一个ip 19 hello world

host模式配置(主机模式)

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

[root@localhost ~]# docker run -it --rm --network host busybox / # ip a   #  指定主机模式用的都是主机的ip 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:bc:11:bf brd ff:ff:ff:ff:ff:ff     inet 192.168.149.130/24 brd 192.168.149.255 scope global noprefixroute ens33        valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue      link/ether 02:42:e7:69:ef:af 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:e7ff:fe69:efaf/64 scope link         valid_lft forever preferred_lft forever / # 

此时如果我们在这个容器中启动一个http站点,我们就可以直接用宿主机的IP直接在浏览器中访问这个容器中的站点了。

 

容器的常用操作

查看容器的主机名

1 [root@localhost ~]# docker run -it --rm  busybox 2 / # hostname   #查看主机名  默认情况下主机名和容器id一样 ,容器里面是只读层,改不了名字,只能在容器启动的时候注入主机名 3 6bd0cb733cbf 4 [root@localhost ~]# docker ps -a 5 CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES 6 6bd0cb733cbf   busybox   sh      36 seconds ago   Up 35 seconds             inspiring_margulis 7   

在容器启动时注入主机名

 1 [root@localhost ~]# docker run -it --rm --hostname node1 busybox  2 / # hostname  3 node1  4 / # cat /etc/hostname   5 node1  6 / # cat /etc/hosts  7 127.0.0.1    localhost  8 ::1    localhost ip6-localhost ip6-loopback  9 fe00::0    ip6-localnet 10 ff00::0    ip6-mcastprefix 11 ff02::1    ip6-allnodes 12 ff02::2    ip6-allrouters 13 172.17.0.2    node1 14 / # mkdir data 15 / # echo 'hello world' > /data/index.html 16 / # /bin/httpd -h /data/ 17 / # netstat -antl 18 Active Internet connections (servers and established) 19 Proto Recv-Q Send-Q Local Address           Foreign Address         State        20 tcp        0      0 :::80                   :::*                    LISTEN    21 / # wget -O - -q node1    #  用主机名也可以访问,因为有映射关系 22 hello world

 

手动指定容器要使用的DNS

1 / # cat /etc/resolv.conf    #  默认的dns 2 # Generated by NetworkManager 3 nameserver 114.114.114.114 4 [root@localhost ~]# docker run -it --rm --hostname node1 --dns 8.8.8.8 busybox   #  手动设置改变dns 5 / # cat /etc/resolv.conf  6 nameserver 8.8.8.8

  7 / # mkdir /data
  8 / # echo 'hello world' > data/index.html
  9 / # /bin/httpd -f -h /data/

 

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

[root@localhost ~]# docker run -it --rm --hostname node2 --add-host node1:172.17.0.2 busybox  # 注入主机名ip地址的映射 / # 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    node1    # 有映射关系了 172.17.0.3    node2 / # wget -O - -q http://node1   #  可以用主机名访问 hello world [root@localhost ~]# docker run -it --rm --hostname node2 --add-host node1:172.17.0.2 --add-host test1:1.1.1.1 --add-host test2:2.2.2.2 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.2    node1 1.1.1.1    test1 2.2.2.2    test2 172.17.0.3    node2

开放容器端口

执行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 -d --rm --name web -p 80 httpd 04fde3b15e0c79356371ed6fd460c707b3d880f196a7452267fdf1bfa3bf9c23 [root@localhost ~]# docker ps CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS                                     NAMES 04fde3b15e0c   httpd     httpd-foreground   8 seconds ago   Up 7 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   web  将指定的容器端口映射至主机所有地址的一个动态端口 [root@localhost ~]# docker run -d --rm --name web -p 80:80 httpd 71765be95b82e4fceb1a9c59a69c1097288e849f159326140016faa0d8803d0b [root@localhost ~]# docker ps CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS                               NAMES 71765be95b82   httpd     httpd-foreground   6 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   web 将容器80端口号映射到主机80端口号 [root@localhost ~]# ip addr add 192.168.149.250/24 dev ens33 [root@localhost ~]# ip a    #  在ens33上增加一个250的ip,现在有两个 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:bc:11:bf brd ff:ff:ff:ff:ff:ff     inet 192.168.149.130/24 brd 192.168.149.255 scope global noprefixroute ens33        valid_lft forever preferred_lft forever     inet 192.168.149.250/24 scope global secondary ens33        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:e7:69:ef:af 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:e7ff:fe69:efaf/64 scope link         valid_lft forever preferred_lft forever 65: veth558e8bf@if64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default      link/ether 9e:42:d0:82:60:31 brd ff:ff:ff:ff:ff:ff link-netnsid 2     inet6 fe80::9c42:d0ff:fe82:6031/64 scope link         valid_lft forever preferred_lft forever [root@localhost ~]# docker run -d --name web --rm -p 192.168.149.130::80 httpd      # 只暴露在130ip上,随机的 741e0771eb296333442514b508ee3476898820b44de58093c0147bd205331771 [root@localhost ~]# 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                          192.168.149.130:49153                            0.0.0.0:*                                 LISTEN           0                 128                                     [::]:22                                  [::]:*  将指定的容器端口<containerPort>映射至主机指定<ip>的动态端口 [root@localhost ~]# docker run -d --name web --rm -p 192.168.149.130:8080:80 httpd  c4e8aa8ea2456d8503e1d305dfa24c3aa3ada4b19d24e68b82ffac442a3988a1 [root@localhost ~]# ss -antl State             Recv-Q            Send-Q                         Local Address:Port                       Peer Address:Port           Process            LISTEN            0                 128                          192.168.149.130:8080                            0.0.0.0:*                                 LISTEN            0                 128                                  0.0.0.0:22                              0.0.0.0:*                                 LISTEN            0                 128                                     [::]:22                                 [::]:* 将指定的容器端口<containerPort>映射至主机指定<ip>的端口<hostPort>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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