Docker容器间互联

允许所有容器互联

默认情况下,同一宿主机下的所有Docker容器相互之间是能够进行网络访问的。

例如,分别启动两个Nginx容器,然后通过其中任意一个Nginx(IP地址:172.17.0.2)可以访问到另一个Nginx(IP地址:172.17.0.3):

# 启动两个 Nginx 容器 nginx_server1、nginx_server2
[root@localhost dockerfiles]# docker run -it -d --name nginx_server1 centos_nginx:1.0  /bin/bash
cac8a92bef84bb2c172548f79810f56d6f431151bc37480ae22f2613de31e477
[root@localhost dockerfiles]# docker run -it -d --name nginx_server2 centos_nginx:1.0  /bin/bash
7ea4342b91b7cc3bed2b900bf4c8b814d6f587a596ad05738f0002d5b4c9bb68

登录其中一个 Nginx 容器,可以访问到另外一个。 

[root@cac8a92bef84 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 213  bytes 328347 (320.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 208  bytes 16152 (15.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
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        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@cac8a92bef84 /]# curl 172.17.0.3
<!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>

通过别名连接容器

在前面的例子中,nginx_server1是通过IP地址来访问的nginx_server2。但是,Docker容器的IP地址是在启动的时候自动分配的,即便是同一个容器在重启时,其IP地址也往往会发生变化。因此,通过IP地址来实现Docker容器之间的相互访问其实并不可靠。

为了解决这一问题,Docker为我们提供了另外一种容器互联方式:通过别名互联。

通过别名互联需要借助 docker run 命令的 --link 参数:

docker run --link [container_name]:[alias] [image] [command]

接下来,我们再启动一个 Nginx 容器命名为 nginx_server3, 并让其连接到 nginx_server2,且为 nginx_server2 指定一个别名为 ng2 。这样一来,nginx_server3 就可以通过 ng2 来访问 nginx_server2 了。

[root@localhost dockerfiles]# docker run -it -d --link nginx_server2:ng2 --name nginx_server3 centos_nginx:1.0  /bin/bash
5942fb62e2d3be6b78722b1826a633094f39aeb208d31417344bf9aa5a577128
[root@localhost dockerfiles]# docker attach 5942fb62e2d3be6b78722b1826a633094f39aeb208d31417344bf9aa5a577128
[root@5942fb62e2d3 /]# curl ng2
<!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>

值得注意的是,此时 nginx_server3 依然可以正常访问宿主机上启动的其他容器。

使用了 --link 参数启动的 Docker容器 其环境变量中会被添加上一些以别名开头的配置项。

[root@5942fb62e2d3 /]# env
HOSTNAME=5942fb62e2d3
TERM=xterm
NG2_PORT_80_TCP_PORT=80
NG2_NAME=/nginx_server3/ng2
NG2_PORT_80_TCP=tcp://172.17.0.3:80
NG2_PORT_80_TCP_PROTO=tcp
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
HOME=/root
NG2_PORT_80_TCP_ADDR=172.17.0.3
NG2_PORT=tcp://172.17.0.3:80
_=/usr/bin/env

 同时,在 /etc/hosts 配置文件中也会添加上该别名的地址映射。

127.0.0.1       localhost

172.17.0.3      ng2 7ea4342b91b7 nginx_server2

禁止所有容器互联

默认情况下,Docker允许位于同一宿主机下的容器之间进行相互访问。如果要改变这一默认配置,需要修改 /etc/docker/daemon.json,添加 icc = false 项。

{

    "icc": false,

    "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"]

}

修改完成后,保存文件并重启 docker 守护进程。

systemctl restart docker

允许指定容器互联

出于安全考虑,我们将Docker的 icc 选项设置为 false ,这样可以禁止所有容器间的相互访问。这时,如果我们需要指定某些容器之间可以进行相互访问,需要做如下配置:

  • 将Docker的 icc 选项设置为 false ,默认情况下,禁止所有容器互联;
  • 将Docker的 iptables 选项设置为 true(默认值,可以不设置) ,启用自定义的iptable规则;
  • 通过 docker run 命令的 --link 参数指定需要进行访问的容器;

在前面的示例中,当我们将Docker的 icc 选项设置为 false 后,nginx_server1 和 nginx_server2 将禁止访问任何其他容器,仅有 nginx_server3 可以访问 nginx_server2 。此时查看 iptables 规则列表,Docker规则链中仅存在一组nginx_server3 和nginx_server2 之间的规则 。

 

[root@localhost dockerfiles]# iptables -L -n
Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-ISOLATION  all  --  0.0.0.0/0            0.0.0.0/0           
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  172.17.0.4           172.17.0.3           tcp dpt:80
ACCEPT     tcp  --  172.17.0.3           172.17.0.4           tcp spt:80

外网访问容器

ip-forward

ip-forward 是 Linux 系统自带的一个配置项,用来决定是否允许系统进行流量转发。在 Docker 中也有一个 ip-forward 选项,其默认值为 true ,这样 Docker 守护进程就会在启动时自动将系统的 ip-forward 参数设置为 1,即允许系统进行流量转发。

# Docker 启动后查看系统 ip-forward 配置
[root@localhost ~]# sysctl net.ipv4.conf.all.forwarding
net.ipv4.conf.all.forwarding = 1

端口映射

在系统允许流量转发的情况下,想要从外网访问容器还需要设置好宿主机和容器之间的端口映射。

[root@localhost dockerfiles]# docker run -it -d -p 8080:80 --name nginx_server4 centos_nginx:1.0 /bin/bash
6a1bae73f56ae16e0d07d8daa2efb142728f0499418ced125122980757a48154
[root@localhost dockerfiles]# docker attach nginx_server4
[root@6a1bae73f56a /]# nginx
[root@6a1bae73f56a /]# [root@localhost dockerfiles]# docker port nginx_server4
80/tcp -> 0.0.0.0:8080

在这里,外面将Nginx容器的80端口映射到了宿主机的8080端口,这样外网就可以通过 http://宿主机IP:8080/ 来访问 nginx 容器了。

iptables

再查看 iptables ,发现Docker规则链中多了一条规则。

[root@localhost ~]# iptables -t filter -L -n
Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  172.17.0.4           172.17.0.3           tcp dpt:80
ACCEPT     tcp  --  172.17.0.3           172.17.0.4           tcp spt:80
# 多的那条规则是我
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.5           tcp dpt:80

 由此可知,外网访问容器是借助 iptables 规则来实现的。既然如此,我们也可以通过自己动手添加 iptables 规则来禁止指定的主机来访问容器。

# 禁止主机 172.16.80.47 访问 容器 172.17.0.5 的 80 端口
[root@localhost dockerfiles]# iptables -I DOCKER -s 172.16.80.47 -d 172.17.0.5 -p TCP --dport 80 -j DROP

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值