即在同一个宿主机上的容器之间能够经过自定义的容器名称相互访问 ,好比一个业务前端静态页面是使用nginx,动态页面使用的是tomcat因为容器在启动的时候其内部IP地址是DHCP随机分配的,因此若是经过内部访问的话,自定义名称是相对比较固定的,所以比较适用于此场景。前端
一、先建立第一个tomcat容器,后续须要将nginx进行转发到此tomcat服务上,tomcat测试页面在Docker之七已经建立,详情请见上一章!!!node
[root@centos-7 ~]# docker run -it -d --name tomcat1 tomcat-app1:v1 dd097a9fd8baaa2da451c279bd9a008c3b7ec36c6cf4a032aa40e697aec549f7
进入到tomcat服务里,查看tomcat的hosts文件linux
[root@centos-7 ~]# docker exec -it tomcat1 bash [root@dd097a9fd8ba /]# 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 dd097a9fd8ba #tomcat的hosts文件解析 1.2.1.3 www.google.net
二、开启一个nginx容器,并将tomcat容器关联起来,启动nginx服务。nginx
[root@centos-7 ~]# docker run -it -d --name nginx-web1 -p 80:80 --link tomcat1 nginx:v1 24549e8fac8fade868004fe6a5c0bc25f04abc08e82f1acffc8c1fcb47e6df65
三、进入nginx服务,而后看nginx的hosts文件web
[root@centos-7 ~]# docker exec -it nginx-web2 bash [root@1e2556622e7b /]# 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 tomcat1 dd097a9fd8ba #能够看到已经将tomcat的host文件关联过来 172.17.0.2 1e2556622e7b
四、进入到nginx配置服务器,而后修改nginx的配置文件,进行转发的tomcat容器部分docker
[root@centos-7 ~]# docker exec -it nginx-web2 bash [root@f53f3ba8b1ad /]# vim /etc/nginx/nginx.conf #修改nginx服务 upstream tomcat { #http段进行修改 server tomcat:8080; #转发到tomcat服务的IP地址和端口,直接转发域名,关联的tomcat服务器的名称不变,就会一直转发到tomcat服务器上 } location /app1 { # server段进行修改 proxy_pass http://tomcat; proxy_set_header Host $host; proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; } [root@f53f3ba8b1ad /]# nginx -t # 测试语法 [root@f53f3ba8b1ad /]# nginx -s reload #从新加载nginx
upstream段转发hosts域名,link连接tomcat的名称,就算tomcat容器删除,IP地址变化以后也没事,只须要从新进行link到同一个名称便可,这样就不须要修改nginx服务器内部配置文件,依然能够访问页面。 shell
此时访问宿主机的IP地址下的app1目录,就会访问到网页:vim
上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,好比程序经过容器名称进行服务调用,可是容器名称发生变化以后再使用以前的名称确定是没法成功调用,每次都进行更centos
改的话又比较麻烦, 所以可使用自定义别名的方式解决,即容器名称能够随意更改,只要不更改别名便可,具体以下:tomcat
命令格式:
docker run -d -name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell 命令
一、从新建立一个tomcat容器,并启动。
[root@centos-7 src]# docker run -it -d --name tomcat2 tomcat-app1:v1
二、将nginx容器与tomcat容器关联,并起一个容器别名,别名为tomcat.google.com
[root@centos-7 ~]# docker run -it -d --name nginx-web3 -p 82:80 --link tomcat2:tomcat.google.com nginx:v1
三、进入nginx容器内,修改nginx配置文件
[root@centos-7 ~]# docker exec -it nginx-web4 bash [root@faf64ae3e99b /]# vim /etc/nginx/nginx.conf location /app1 { proxy_pass http://tomcat.google.com:8080; #直接监听别名解析 } [root@faf64ae3e99b /]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@faf64ae3e99b /]# nginx -s reload
测试页面,此时容器启动nginx监听的是82端口,所以须要82端口进行访问:
同一个宿主机之间的各容器之间是能够直接通讯的,可是若是访问到另一台宿主机的容器呢?
下面我来介绍一下docker网络模式:
用命令直接查看网络模式:bridge、host、none、container四种模式。
Host模式,使用参数--net=host指定,Host模式不支持端口映射,且容器没法启动。
启动的容器若是指定了使用host模式,那么新建立的容器不会建立本身的虚拟网卡(Network Namespace),而是直接使用宿主机的网卡和IP地址(Network Namespace),所以在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口便可,不过容
器的其余资源们必须文件系统、系统进程等仍是和宿主机保持隔离。此模式的网络性能最高,可是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。
[root@centos-7 ~]# docker run -it -d --name nginx-net-host --net=host nginx:v1 # 打开指定host模式的容器 ac4e0be49a668d19935d9158e7e6a1c81c7afeac0d3dde88349979ab26e311dc [root@centos-7 ~]# docker exec -it nginx-net-host bash # 进入到容器中 [root@centos-7 /]# ip a #查看此host容器模式的IP地址,就是使用的是宿主机的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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:59:4a:1d brd ff:ff:ff:ff:ff:ff inet 192.168.7.100/24 brd 192.168.7.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe59:4a1d/64 scope link 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:a6:2c:bb:07 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:a6ff:fe2c:bb07/64 scope link valid_lft forever preferred_lft forever
使用none模式,Docker容器拥有本身的Network Namespace,可是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有lo 网络接口。须要咱们本身为Docker容器添加网卡、配置IP等。
不参与网络通讯,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通讯的场景中,例如:备份、进程诊断及各类离线任务等,此模式极少使用。
[root@centos-7 ~]# docker run -it -d --name nginx-net-host1 --net=none nginx:v1 # 建立none网络模式 dd00a68d3853602902aae3b08f57c06827b649f764f951a60bc7e4c2298a0ea4 [root@centos-7 ~]# docker exec -it nginx-net-host1 bash [root@dd00a68d3853 /]# 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 [root@dd00a68d3853 /]# ifconfig 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 Namespace,而不是和宿主机共享。新建立的容器不会建立本身的网卡,配置本身的 IP,而是和一个指定的容器共享 IP、端口范围等。一样,两个容器除了网络方面,其余的如文件系统、进程列表等仍是隔离的。两个容器的进程能够经过 lo 网卡设备通讯。
(1)在一个终端,使用bridge网络模式启动容器tomcat1
[root@centos-7 ~]# docker run -it --name tomcat1 --net=bridge -d tomcat-app1:v1 10753fcfcd45b06eac55badca2166dcca5c76e26260d99bfa945f68ae8a50454 [root@centos-7 ~]# docker exec -it tomcat1 bash [root@10753fcfcd45 /]# ip a #查看此时的IP地址是172.17.0.2 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 50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
(2)在另外一个终端使用Container 网络模式建立容器tomcat2
[root@centos-7 ~]# docker run -it -d -name tomcat2 --net=container:tomcat1 tomcat-app1:v1 # 建立tomcat2容器 [root@centos-7 ~]# docker exec -it tomcat2 bash #进入到tomcat2 [root@10753fcfcd45 /]# ip a # 查看IP地址,此时的IP地址就和桥接模式的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 50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
当Docker进程启动时,会在主机上建立一个名为docker0的虚拟网桥,此主机上启动的Docker容器会链接到这个虚拟网桥上,因此有默认地址172.17.0.0/16的地址。虚拟网桥的工做方式和物理交换机相似,这样主机上的全部容器就经过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上建立一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新建立的容器中,并命名为eth0(容器的网卡),另外一端放在主机中,以vethxxx这样相似的名字命名,并将这个网络设备加入到docker0网桥中。能够经过brctl show命令查看。
[root@centos-7 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242a62cbb07 no veth4f25042
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables作了DNAT规则,实现端口转发功能。可使用iptables -t nat -vnL查看。
[root@centos-7 ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 31 packets, 5027 bytes) pkts bytes target prot opt in out source destination 31 1588 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 31 packets, 5027 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 69 packets, 4024 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 69 packets, 4024 bytes) pkts bytes target prot opt in out source destination 233 14471 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
A主机:10.20.0.1/16
B主机:10.10.0.1/16
一、修改A主机的docker配置文件,指定docker容器的IP地址
[root@openstack ~]# vim /lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip 10.20.0.1/16 [root@openstack ~]# systemctl daemon-reload [root@openstack ~]# systemctl restart docker
二、查看此时修改后的docker0的IP地址,此时就是修改后的IP地址
一、修改B主机的docker地址,指定一个地址10.10.0.1/16
[root@centos-7 ~]# vim /lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 192.168.7.103 --insecure-registry 192.168.7 .102 --bip=10.10.0.1/16 [root@centos-7 ~]# systemctl daemon-reload [root@centos-7 ~]# systemctl restart docker
二、查看修改后的IP地址
一、A主机开启一个容器
[root@centos-7 ~]# docker run -it -d --name nginx-web1 nginx:v1 7a77bc53509d6e14f25b5a217e1b47ccf8af61ac7e6011786512131c6803a16f
二、B主机开启一个容器
[root@openstack ~]# docker run -it -d --name nginx-web2 goharbor/harbor-db:v1.7.5
一、在A主机添加B主机的IP地址段和B主机的宿主机IP地址,并添加一个防火墙规则
[root@centos-7 src]# route add -net 10.20.0.0/16 gw 192.168.7.102 [root@centos-7 src]# iptables -A FORWARD -s 192.168.7.0/21 -j ACCEPT #容许此IP地址段的均可以访问
二、在B主机添加A主机的IP地址段和A主机的宿主机IP地址,并添加防火墙规则
[root@centos-7 src]# route add -net 10.10.0.0/16 gw 192.168.7.102 [root@centos-7 src]# iptables -A FORWARD -s 192.168.7.0/21 -j ACCEPT #容许此IP地址段的均可以访问
三、进入A主机开启的容器内部,而后ping测试B主机是否可以ping通
[root@centos-7 ~]# docker exec -it nginx-web1 bash [root@7a77bc53509d /]# ping 10.10.0.1 PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data. 64 bytes from 10.10.0.1: icmp_seq=1 ttl=64 time=0.078 ms 64 bytes from 10.10.0.1: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 10.10.0.1: icmp_seq=3 ttl=64 time=0.050 ms 64 bytes from 10.10.0.1: icmp_seq=4 ttl=64 time=0.049 ms
四、此时B主机ping A主机也能够通
[root@openstack ~]# docker exec -it 8b86881da848 bash root [ / ]# ping 10.20.0.1 PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data. 64 bytes from 10.10.0.2: icmp_seq=1 ttl=62 time=0.700 ms 64 bytes from 10.10.0.2: icmp_seq=2 ttl=62 time=0.485 ms 64 bytes from 10.10.0.2: icmp_seq=3 ttl=62 time=0.465 ms
一、建立一个网络名称
[root@centos-7 ~]# docker network create -d bridge --subnet 172.27.0.0/21 --gateway 172.27.0.1 linux36-net
查看建立成功的网络信息,此时能够看到linux36-net就是本身建立的网络
[root@centos-7 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE f2926808018e bridge bridge local 7706b813f5bf host host local 4e9a106f0e22 linux36-net bridge local 498b37d89d4e none null local
二、运行一个centos镜像,此时就能够看到一个自定义的网络分配给镜像一个IP地址
[root@centos-7 ~]# docker run -it --network linux36-net centos bash # 使用本身建立的网络IP地址段 [root@8409e98a804d /]# ip a # 拿到的IP地址是172.27.0.2/21 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 55: eth0@if56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.27.0.2/21 brd 172.27.7.255 scope global eth0 valid_lft forever preferred_lft forever
三、此时就能够ping通外网的地址
[root@8409e98a804d /]# ping www.baidu.com PING www.a.shifen.com (112.80.248.75) 56(84) bytes of data. 64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=1 ttl=127 time=32.6 ms 64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=2 ttl=127 time=50.3 ms
四、此时再启动一个容器A,查看最新的容器IP地址,因为和上面建立的容器,在一个地址段,所以也能够进行通讯
[root@centos-7 src]# docker run -it -p 80:80 --network linux36-net nginx:v1 bash [root@b3afcaea2c02 /]# ip a #查看新建的容器的IP地址是172.27.0.3,在同一个网段。 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 61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.27.0.3/21 brd 172.27.7.255 scope global eth0 valid_lft forever preferred_lft forever
五、为了将两个跨主机且不在同一网段的宿主机进行通讯
[root@centos-7 src]# iptables-save > iptables-rule.txt #将iptables规则导出,而后修改此配置文件,注释掉如下两行 #-A DOCKER-ISOLATION-STAGE-2 -o br-4e9a106f0e22 -j DROP #-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP [root@centos-7 src]# iptables-restore < iptables-rule.txt # 再将iptables规则再导回来
六、而后开启个桥接模式的容器B
[root@centos-7 src]# docker run -d -it -p 81:80 --network bridge nginx:v1 #启动一个桥接模式的容器 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a [root@centos-7 src]# docker exec -it 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a bash [root@0274bd84109a /]# ip a # 获取的IP地址是10.10.0.3/16 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 65: eth0@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:0a:0a:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.10.0.3/16 brd 10.10.255.255 scope global eth0 valid_lft forever preferred_lft forever
七、而后进入容器B中进行ping容器A的IP地址,此时就会基于iptables规则进行跨网段ping通
[root@centos-7 src]# docker run -d -it -p 81:80 --network bridge nginx:v1 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a [root@centos-7 src]# docker exec -it 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a bash # 进入到B容器中 [root@0274bd84109a /]# 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 65: eth0@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:0a:0a:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.10.0.3/16 brd 10.10.255.255 scope global eth0 valid_lft forever preferred_lft forever [root@0274bd84109a /]# ping 172.27.0.3 #ping容器A的IP地址,此时能够ping通 PING 172.27.0.3 (172.27.0.3) 56(84) bytes of data. 64 bytes from 172.27.0.3: icmp_seq=1 ttl=63 time=0.335 ms 64 bytes from 172.27.0.3: icmp_seq=2 ttl=63 time=0.069 ms 64 bytes from 172.27.0.3: icmp_seq=3 ttl=63 time=0.070 ms ^C --- 172.27.0.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 3ms rtt min/avg/max/mdev = 0.069/0.158/0.335/0.125 ms