Docker中使用bridge网络

2020年1月8日
Docker中使用bridge网络插图

本文出自明月工作室:https://www.freebytes.net/it/linux/docker-network-bridge.html

bridge网络

bridge网络,也就是docker的桥接网络,可简称“网桥”。

就网络而言,网桥是一个能在不同网段之间转发流量的链路层设备。桥可以是运行在主机内核的软件设备或硬件设备。
但是就docker而言,网桥是一个软件设备,它允许在同一个桥接网络内的不同容器相互通信,同时隔离不在此网络内的容器。
Docker网桥驱动程序会自动在主机中安装、配置规则,以使不同网桥网络上的容器无法直接相互通信。

桥接网络适用于在同一Docker守护进程主机上运行的容器。
为了在不同Docker守护进程主机上运行的容器之间进行通信,可以在OS级别管理路由,也可以使用overlay network。

启动Docker时,会自动创建一个默认的桥接网络,新启动的容器将默认连接到该网络。

但是我们一般创建自己定义的桥接网络。用户定义的桥接网络优于默认bridge网络。

用户定义的网桥和默认网桥之间的区别

1. 用户定义的桥在容器之间提供更好的隔离和互操作性。

连接到同一用户定义的网桥的容器会自动将所有端口彼此公开,而不会向外界公开任何端口。这使容器化的应用程序可以轻松地彼此通信,而不会意外打开对外界的访问。

eg:以一个具有Web前端和数据库后端的应用程序作为例子。
外界需要访问Web前端(也许在端口80上),但是只有后端本身需要访问数据库主机和端口。使用用户定义的网桥,只需打开Web端口,并且数据库应用程序不需要打开任何端口,因为Web前端可以通过用户定义的网桥到达它。如果在默认网桥网络上运行相同的应用程序堆栈,则需要使用-p或–publish 标志分别打开Web端口和数据库端口。这意味着Docker主机需要通过其他方式阻止外界对数据库端口的访问。

2. 用户定义的网桥可在容器之间提供自动DNS解析。

在用户定义的网桥网络上,容器可以通过名称或别名相互解析。默认桥接网络上的容器只能通过IP地址相互访问,除非使用–link选项在容器之间手动创建连接,但这些链接需要双向创建,因此,当进行通信的容器超过两个,操作将变得很复杂。

3. 容器可以随时随地从用户定义的网络连接和分离。

在容器的生命周期内,您可以即时将其与用户定义的网络连接或断开连接。要从默认桥接网络中删除容器,您需要停止容器并使用其他网络选项重新创建它。

使用默认网桥

docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

其中bridge就是默认的桥接网络。现在启动两个容器, 由于未指定任何 --network标志,因此容器将连接到默认bridge网络。

docker pull alpine 

docker run -dit --name alpine1 alpine ash

docker run -dit --name alpine2 alpine ash

此时,可以 检查bridge网络连接了哪些容器:

docker network inspect bridge


"Containers": {
            "602dbf1edc81813304b6cf0a647e65333dc6fe6ee6ed572dc0f686a3307c6a2c": {
                "Name": "alpine2",
                "EndpointID": "03b6aafb7ca4d7e531e292901b43719c0e34cc7eef565b38a6bf84acf50f38cd",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "da33b7aa74b0bf3bda3ebd502d404320ca112a268aafe05b4851d1e3312ed168": {
                "Name": "alpine1",
                "EndpointID": "46c044a645d6afc42ddd7857d19e9dcfb89ad790afb5c239a35ac0af5e8a5bc5",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

此时,alpine2的ip是172.17.0.3,alpine1的ip是172.17.0.2,在两个容器里面,可以相互ping通对方的ip,但是不能ping通对方的容器名,因为默认的网桥并不提供相关的DNS解析。

使用用户定义的网桥网络

1、创建alpine-net网络。--driver bridge因为是默认标志,所以其实可以不用写出来。

docker network create --driver bridge alpine-net

2、此时可查看Docker的网络,发现多了一个:

docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
e9261a8c9a19        alpine-net          bridge              local
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

3、将两个容器加入到alpine-net网络中:

docker run -dit --name alpine3 --network alpine-net alpine ash

docker run -dit --name alpine4 --network alpine-net alpine ash

4、此时查看alpine-net网络,发现alpine3 和alpine4已在网络中:

docker network inspect alpine-net

  "Containers": {
            "0a02c449a6e9a15113c51ab2681d72749548fb9f78fae4493e3b2e4e74199c4a": {
                "Name": "alpine3",
                "EndpointID": "c83621678eff9628f4e2d52baf82c49f974c36c05cba152db4c131e8e7a64673",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "156849ccd902b812b7d17f05d2d81532ccebe5bf788c9a79de63e12bb92fc621": {
                "Name": "alpine4",
                "EndpointID": "058bc6a5e9272b532ef9a6ea6d7f3db4c37527ae2625d1cd1421580fd0731954",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },

5、进入其中一个容器,ping另一个容器的ip或者容器名,都可以ping通。

管理用户定义的网桥

1、 创建用户定义的网桥网络

docker network create 网络名

2、 使用该docker network rm命令删除用户定义的网桥网络。如果容器当前已连接到网络, 请先断开它们的连接 。

docker network rm 网络名

3、要将运行中的容器与用户定义的网桥断开连接

docker network disconnect 网络名 容器名

4、要将运行中的容器连接到现有的用户定义的网桥

docker network connect 网络名 容器名

5、将容器连接到用户定义的网桥创建新容器时,可以指定一个或多个–network标志。本示例将Nginx容器连接到my-net网络。它还将容器中的端口80发布到Docker主机上的端口8080,以便外部客户端可以访问该端口。连接到my-net 网络的任何其他容器都可以访问该my-nginx容器上的所有端口,反之亦然。

 docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest

注意

尽量不要在同一网络中,使多个容器的内部端口出现相同的情况,否则在容器互联时,会出现莫名的错误。比如:nginx容器使用 -p 8081:80 ,而wordpress容器使用-p 80:80,nignx使用桥接网络代理到wordpress时,会出现无法代理的情况。

另外,推荐一篇更具实用性的docker容器互联的文章:docker网络组建