Docker提供网络服务
当我们在容器中运行一些网络服务,如httpd,nginx,php等。要让外部用户可以访问这些服务,这就需要我们进行一些配置,才能达到这些效果。如端口映射或容器互联的方式。
端口映射方式
我们可以在启动容器的时候用-p或-P参数来制定端口映射。使用-p参数指定一个指定的端口映射到容器应用中,而使用-P是选择一个随机的端口映射到容器应用端口中。
方式一:使用-p参数,指定一个映射的端口,且这个被指定的端口只能绑定一个容器
# 绑定方式一: hostport:containerPort
[root@hd3 ~]# docker run -d -p 88:80 --name myweb nginx dac9b2d7ecab288e3fd3186e34941a78b94f4cee9368a3f0ccef8b8136a590a0 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dac9b2d7ecab nginx "/docker-entrypoint.…" 4 seconds ago Up 2 seconds 0.0.0.0:88->80/tcp myweb [root@hd3 ~]# curl localhost:88 <!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>
# 绑定方式二:host:port:containerPort [root@hd3 ~]# docker run -d -p 127.0.0.1:89:80 --name myweb nginx 1ce3a804f6ed20beaa353e7b9a8d8069c75f592a529fcbf95e23564a52c1d634 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1ce3a804f6ed nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 127.0.0.1:89->80/tcp myweb [root@hd3 ~]# curl 127.0.0.1:89
# 绑定方式三:host::containerPort 这种方式是选择一个该主机的随机端口 [root@hd3 ~]# docker run -d -p 127.0.0.1::80 --name myweb nginx 93a420d642bc36ec1f3c53bf10959b9b252603a5caff75cabc19c26a4e7f007f [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 93a420d642bc nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 127.0.0.1:32768->80/tcp myweb [root@hd3 ~]# curl 127.0.0.1:32768
# 可以指定映射端口的连接协议
[root@hd3 ~]# docker run -d -p 127.0.0.1:82:80/udp --name myweb nginx 34917ff1230b6a8d072507df71053afee430435fd1cd232c06f010b69eb663d0 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 34917ff1230b nginx "/docker-entrypoint.…" 3 seconds ago Up 1 second 80/tcp, 127.0.0.1:82->80/udp myweb
# 也可以一次性绑定多个端口 [root@hd3 ~]# docker run -d -p 88:80 -p 89:443 --name myweb nginx 76764e3c6fa2e15b28dd3da5bba28713c00d89516953927cef10c290169ea112 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76764e3c6fa2 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:88->80/tcp, 0.0.0.0:89->443/tcp myweb
方式二:使用-P参数,Docker会随机映射一个端口到内部的网络开放的端口和上述的第三种情况类似
[root@hd3 ~]# docker run -d -P --name myweb nginx 6e8f0737f38efea2c183b97babeaf5bc2bc12e4fa417ba5198b8cf04e75f0f6b [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6e8f0737f38e nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:32772->80/tcp myweb
通过docker logs -f containername可以查看docker日志信息
[root@hd3 ~]# docker logs -f myweb /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Configuration complete; ready for start up
通过docker ports containername查看容器端口信息
[root@hd3 ~]# docker port myweb 80/tcp -> 0.0.0.0:32772 [root@hd3 ~]#
Docker容器互联
容器的连接系统除了端口映射外,另一种是容器的交互方式。该系统会在源和接受容器之间创建一个隧道,接受容器可以看到源容器指定的信息。
使用 --link参数可以让容器与容器之间进行安全的交互
[root@hd3 ~]# docker run -e MYSQL_ROOT_PASSWORD=123456 -d --name mydb mysql # 先启动一个mysql容器 5b835f77eb9ad738ce55286ce1837ed84f59eab3c7a25a2e52b12a457f548fad [root@hd3 ~]# docker run -d -P --name myweb --link mydb:db nginx # 再启动一个web容器,并将它连接到数据库容器中 e74c38a73c7eee83fe017540f92284e5a71293c7159e1397a845a638b801d515 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e74c38a73c7e nginx "/docker-entrypoint.…" 4 seconds ago Up 2 seconds 0.0.0.0:32773->80/tcp myweb 5b835f77eb9a mysql "docker-entrypoint.s…" 34 seconds ago Up 33 seconds 3306/tcp, 33060/tcp mydb
从上面可以看到,此时myweb和mydb容器已经相互连接起来
--link 参数的格式: --link name:alias
name:是要链接的容器的名称,
alias:是这个链接的别名
Docker容器之间的互联,是在容器与容器之间建立一个安全的隧道,而且不用映射他们的端口到主机上,在启动mydb容器的时候没有使用-p或-P参数,从而避免了暴露过多的端口到外部网络上。
Docker通过两种方式为容器公开连接的信息:
1. 环境变量
2. 更新/etc/hosts文件
通过env可以查看环境变量
[root@hd3 ~]# docker run --rm --name myweb01 --link mydb:db nginx env DB_PORT_33060_TCP_ADDR=172.17.0.2 HOSTNAME=37a871abaf9d DB_PORT=tcp://172.17.0.2:3306 DB_PORT_3306_TCP=tcp://172.17.0.2:3306 DB_PORT_33060_TCP_PORT=33060 DB_ENV_MYSQL_VERSION=8.0.21-1debian10 DB_PORT_33060_TCP_PROTO=tcp HOME=/root DB_NAME=/myweb01/db PKG_RELEASE=1~buster DB_PORT_33060_TCP=tcp://172.17.0.2:33060 NGINX_VERSION=1.19.1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NJS_VERSION=0.4.2 DB_ENV_MYSQL_MAJOR=8.0 DB_PORT_3306_TCP_ADDR=172.17.0.2 DB_ENV_MYSQL_ROOT_PASSWORD=123456 PWD=/ DB_ENV_GOSU_VERSION=1.12 DB_PORT_3306_TCP_PORT=3306 DB_PORT_3306_TCP_PROTO=tcp
其中DB_开头的环境变量是供web容器连接 DB 容器使用的。可以看到连接容器的协议,端口,密码等
除了环境变量,Docker 还添加host信息到父容器的 /etc/hosts 的文件:
[root@hd3 ~]# docker run --rm -it --name myweb03 --link mydb:db nginx /bin/bash root@f1ee3a4dec86:/# 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 db 5b835f77eb9a mydb 172.17.0.4 f1ee3a4dec86
可以看到这里有2个hosts,第一个是 web 容器,web容器用id作为他的主机名,第二个是 DB 容器的 ip 和主机名。可以在web 容器中使用ping命令来测试跟 DB 容器的连通。
Docker四种网络模式
Host模式
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
表现形式:容器和宿主IP一致
特点: 用于网络性能要求较高的场景,但安全性和隔离性相对差一些
结构如下:
配置方式:--network host
[root@hd3 ~]# docker run -itd --name host_test --network host centos # 指定网络模式 837dd3e985b2b7e936940ee44b5cab13dc6d02a05c225a24c2e19f13c06c2d2c [root@hd3 ~]# docker exec -it host_test /bin/bash [root@hd3 /]# ip a # 进入容器可以发现连容器的主机名也和宿主的主机名一致,通过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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:4b:a1:4f brd ff:ff:ff:ff:ff:ff inet 192.168.239.132/24 brd 192.168.239.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever 。。。 [root@hd3 /]# exit exit [root@hd3 ~]# 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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:4b:a1:4f brd ff:ff:ff:ff:ff:ff inet 192.168.239.132/24 brd 192.168.239.255 scope global noprefixroute ens32 。。。
Bridge模式
bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。类似于Vmware的nat网络模式。同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的。docker进程会创建一个docker0网桥,容器内的数据通过这个网卡设备于主机之间进行通讯。
特点:
配置方式:默认情况下就是bridge的模式
[root@hd3 ~]# docker run -d -it --name bridge_test centos 083ba95f39ae455be1f91efaa00a368db5bbf452a611ff2a0c4d39d2889a9d78 [root@hd3 ~]# [root@hd3 ~]# docker inspect bridge_test [ 。。。。。。。。。。 "Networks": { # 这一行显示了该容器的网络是bridge "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "80c570b6c4ea28598da690765604caa14e02882735dc86807b6950205be8219c", "EndpointID": "e62963d786270c3d1f68b5c5aba10dfaa9a1d6328807409e894976c4aa983aaf", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ] [root@hd3 ~]# docker exec -it bridge_test /bin/bash [root@083ba95f39ae /]# 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 123: eth0@if124: <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 [root@083ba95f39ae /]# ping www.baidu.com PING www.a.shifen.com (180.101.49.12) 56(84) bytes of data. 64 bytes from 180.101.49.12 (180.101.49.12): icmp_seq=1 ttl=127 time=36.1 ms
注意: 若该默认方式容器无法访问外网可以查看一下该配置 sysctl net.ipv4.ip_forward 1 # 若该值为0则无法访问外网 sysctl -w net.ipv4.ip_forward=1 # 将其修改为1
Container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
表现形式:多个容器使用的是共同的网络,看到的IP也是一致的。
特点:K8S中的pod就是使用这种模式,平时使用不多
结构如下:
[root@hd3 ~]# docker run -itd --name container_test --net=container:bridge_test centos # 指定为container模式 0ab83d070c9c9ecff083a91ae4c3a5324c4b72eb4f726a4223cff0f31c5fd5f0 [root@hd3 ~]# docker attach container_test [root@083ba95f39ae /]# ip a # 查看ip发现和上面bridge的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 123: eth0@if124: <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
None模式
在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
[root@hd3 ~]# docker run -itd --name none_test --network none centos # 指定为none模式 ac35a1a7d54315b917197ce8a73f3b328ad78348f7f919144d34824459f7dab3 [root@hd3 ~]# docker attach none_test [root@ac35a1a7d543 /]# 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
自定义网络
与默认的bridge一样,但是自定义的网络具备内部的DNS发现,可以通过容器名或主机名进行容器之间的相互通信。
[root@hd3 ~]# docker network create test_network # 自定义一个网络 cb23126382b281f7e9ec21dfb7471d0d1db382773b3b6596b05526b36deb49c9 [root@hd3 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 80c570b6c4ea bridge bridge local 7a4c931b7874 host host local 671303b2ec10 lnmp bridge local 89b85fcb7fd0 none null local cb23126382b2 test_network bridge local # 可以看到我们自己定义的网络
[root@hd3 ~]# docker run -itd --name test1 --net=test_network centos # 创建容器指定自定义的网桥 5137f1f35471832a65a275537dde5cef5671841fd18ac53ee5b0fccd0426a4c0 [root@hd3 ~]# docker run -itd --name test2 --net=test_network centos 58bf03132e8a8c51ffbe2d7ee9f4572233007de1d8d0383b7cef31968df34f6c [root@hd3 ~]# docker attach test1 [root@5137f1f35471 /]# ping test2 # 进入网桥ping 可以自定义解析test2 PING test2 (172.19.0.3) 56(84) bytes of data. 64 bytes from test2.test_network (172.19.0.3): icmp_seq=1 ttl=64 time=0.714 ms 64 bytes from test2.test_network (172.19.0.3): icmp_seq=2 ttl=64 time=0.077 ms [root@5137f1f35471 /]# 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.19.0.2 5137f1f35471
Docker的DNS配置
我们在创建容器的时候,并没有指定主机名和DNS等配置,如果我们需要配置,那么怎么自定义配置容器的主机名和DNS配置?里面的原理有事什么样的呢?
秘诀就是它利用虚拟文件来挂载到容器的3个相关的配置文件:
[root@hd3 ~]# docker run --rm --name mydocker -it centos /bin/bash [root@20265bbb21cd /]# mount # 查看挂载信息 。。。 /dev/sda3 on /etc/resolv.conf type xfs (rw,relatime,seclabel,attr2,inode64,noquota) /dev/sda3 on /etc/hostname type xfs (rw,relatime,seclabel,attr2,inode64,noquota) /dev/sda3 on /etc/hosts type xfs (rw,relatime,seclabel,attr2,inode64,noquota) 。。。
这种机制可以让宿主机DNS信息发生更新后,所有Docker容器的 dns 配置通过 /etc/resolv.conf 文件立刻得到更新。
如果想要手动指定容器的配置,可以利用下面的选项。
-h HOSTNAME or --hostname=HOSTNAME 设定容器的主机名,它会被写到容器的/etc/hostname 和 /etc/hosts。 但它在容器外部看不到,既不会在docker ps中显示,也不会在其它容器的 /etc/hosts看到
--link=CONTAINER_NAME:ALIAS 选项会在创建容器的时候,添加一个其他容器 的主机名到/etc/hosts 文件中,
让新容器的进程可以使用主机名 ALIAS 就可以 连接它。
--dns=IP_ADDRESS 添加DNS服务器到容器的 /etc/resolv.conf中,让容器利用这个服务器来解析所有不在 /etc/hosts 中的主机名
[root@hd3 ~]# docker run --rm --name mydocker -h host_test -it centos /bin/bash # 指定主机名 [root@host_test /]# cat /etc/hostname # 查看一下主机名是我们指定的 host_test [root@host_test /]# cat /etc/hosts # 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 host_test
注意:如果没有--dns 和--dns-search选项时,Docker会默认用宿主机上的 /etc/resolv.conf 来配置容器。
Docker容器访问控制
容器访问外网
容器的访问控制,主要通过Linux上的 iptables 防火墙来进行管理和实现。
容器要想访问外部网络,需要本地系统的转发支持,在linux系统中,检查转发是否打开
[root@hd3 ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
如果为0,说明没有开启转发,则需要手动打开
[root@hd3 ~]# sysctl -w net.ipv4.ip_forward=1
注意:
如果在启动Docker服务的时候指定 --ip-forward=true,Docker就会自动设定系统的 ip_forward 参数为1。
处理参数原因,另一个就是防火墙了,容器所有到外部网络的连接,源地址都会被NAT成本地系统的IP地址,这是使用iptables 的源地址伪装操作实现的。
查看主机的NAT规则
[root@wallace ~]# iptables -t nat -nL Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LO # 默认情况下是可以出去的.
容器之间访问
默认情况下,容器之间是可以相互通信的
容器之间的访问需要两个方面的支持:
1. 容器的网络拓扑是否已经互联,默认情况下,所有的容器都会
2. 本地系统的 iptable 是否允许
访问所有的端口
当启动Docker服务时, 默认会添加一条转发策略到iptables的FORWARD链上, 策略为通过(ACCEPT)还是禁止(DROP)取决于配置--icc=true 还是 --icc=false。如果手动指定 --iptables=false 则不会添加iptables 规则。
可见,默认情况下,不同容器之间是允许网络互通的。如果是为了安全考虑,可以在/etc/default/docker 文件中配置 DOCKER_OPTS=--icc=false 来禁止它。
外部网络访问容器
容器允许外部访问,可以在docker run 时候通过 -p 或 -P 参数来启用。不论用哪种,其实也是在本地的 iptables 的nat表中添加相应的规则。
使用 -P 时:
[root@server ~]# iptables -t nat -nL #查看防火墙nat表的规则 ... Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:32770 to:172.17.0.3:443 DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:32771 to:172.17.0.3:80 ...
使用 -p 88:80 时:
[root@server ~]# iptables -t nat -nL #查看防火墙规则 Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:88 to:172.17.0.5:80
注意:这里规则映射了 0.0.0.0,意味着将接收主机来自所有的接口的流量。
配置docker0网桥
Docker 服务默认会创建一个 docker0 网桥(其实有一个 docker0 内部接口),它在内核层连通了其它的物理网卡或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
Docker 默认指定了 docker0 接口的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了MTU(接口允许接收的最大传输单元),通常是1500Bytes,或宿主机网络路由上支持的默认值,这些值都可以在服务启动的时候进行配置。
--bip=CIDR --IP地址加掩码格式,例如 192.168.1.2/24 --mtu=BYTES --覆盖默认的 Docker mtu配置
也可以在配置文件中配置 DOCKER_OPTS, 然后重启服务,由于目前Docker网桥是Linux网桥,可以使用 brctl show 来查看网桥和端口连接信息
[root@server ~]# brctl show #查看网桥和端口信息 bridge name bridge id STP enabled interfaces docker0 8000.0242d8da46c0 no veth07c5f5c veth0bed0f7
每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上 docker0 接口的IP 作为所有容器的默认网关
[root@server ~]# docker run -it --rm --name myCentos centos /bin/bash [root@4636797a8e7c /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.6 netmask 255.255.0.0 broadcast 172.17.255.255 ... [root@4636797a8e7c /]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
自定义网桥
除了默认的 docker0 网桥,也可以指定网桥来连接各个容器
在启动Docker 服务的时候, 使用 -b BRIDGE 或 --bridge=BRIDGE 来指定使用的网桥
(1)先创建网桥
[root@server ~]# systemctl stop docker #停止docker服务 [root@server ~]# ip link set dev docker0 down #停止docker0网桥 [root@server ~]# brctl delbr docker0 #删除docker0网桥 [root@server ~]# brctl addbr bridge0 #新建bridge0网桥 [root@server ~]# ip addr add 192.168.2.1/24 dev bridge0 #绑定ip给bridge0网桥 [root@server ~]# ip link set dev bridge0 up #启动bridge0网桥 [root@server ~]# brctl show #查看网桥信息 bridge name bridge id STP enabled interfaces bridge0 8000.000000000000 no virbr0 8000.525400caf93e yes virbr0-nic [root@server ~]# ifconfig bridge0 #查看bridge0网桥信息 bridge0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.2.1 netmask 255.255.255.0 broadcast 0.0.0.0
( 2 )配置docker
[root@server ~]# vim /lib/systemd/system/docker.service #由于新版本的没有/etc/default/docker配置文件,so 需要自己添加。 ExecStart=/usr/bin/dockerd -H unix:// $DOCKER_OPTS #在ExecStart末尾添加 $DOCKER_OPTS EnvironmentFile=-/etc/default/docker #指定配置文件的路径 [root@server ~]# vim /etc/default/docker #自定义编辑配置文件,写入启动指定网桥的网桥信息 DOCKER_OPTS="-b=bridge0" [root@server ~]# systemctl start docker #启动docker服务 [root@server ~]# docker run --rm -ti --name Mycentos centos /bin/bash #创建一个容器 [root@0a13bd05faae /]# ifconfig #查看容器的ip地址,检查是否桥接到birdge0上面 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.2.2 netmask 255.255.255.0 broadcast 192.168.2.255 [root@0a13bd05faae /]# ping 192.168.2.1 #测试和网桥是否通 PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data. 64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.094 ms
说明:在老版本docker上面默认就有/etc/default/docker配置文件,直接编辑即可, 在新版本上面没有,所以需要自己指定。