在 Docker 中使用桥接网络

本文是一篇译文,原文地址
在 Docker 中使用的桥接网络是通过软件桥接的方式,允许连接在同一个桥接网络下的容器可以相互访问,同时,隔离没有连接在该桥接网络下的容器。Docker 桥接驱动器自动在宿主设备上安装了协议,因此,不同桥接网络下的容器,无法直接进行相互访问。

桥接网络,适用于通过同一个 Docker 伴随进程宿主的容器之间。不同伴随进程宿主之间,可以通过 OS 层的路由或者通过 overlay network 完成。

当启动 Docker 时,默认桥接网络将会被自动创建。新加进来的容器自动连接到该网络中,除非你指定了不同。当然,你也可以创建用户自定义网络。

用户自定义桥接网络和默认桥接网络的不同

  • 用户自定义桥接网络提供自动 DNS 解析
    在默认桥接网络中的容器,可以通过 IP 地址相互访问,除非你使用 –link 选项,但是该选项已经被考虑废弃了。在用户自定义的桥接网络中,容器之间可以通过名字或者别称相互访问。

考虑一种场景,一个应用具有 web 前端和数据库后端,分别位于 web 和 db 容器中。web 需要连接到 db。
如果它们被放置在同一个应用中,且使用了默认的桥接网络,则需要在两者之间创建链接(使用 - - flag 标志)。这个连接标志需要在两边都创建,才能实现相互访问。这看起来就比较复杂。
或者,也可以通过操作 /etc/hosts 文件内,但是这很难 debug.

  • 用户桥接网络提供了更好的隔离措施
    所有的容器,如果不使用 --network 指定,默认的都连接在默认桥接网络下。这种使用方式是有风险的,一些不相关的服务、容器、应用都可以相互访问。

使用用户定义的桥接网络,将实现很好的访问隔离。只有连接在该网络中的容器可以相互访问。

  • 用户定义网络中,容器连接在网络中或从网络中退出都是实时操作的
    在容器的生命周期中,连接到或者退出连接,在用户自定义网络中可以是实时的,不需要关闭容器。而在默认桥接网络中,需要停止容器,然后使用不同网络配置重建它。

  • 每个用户自定义网络都创建了一个可配置的桥接
    如果容器使用了默认桥接网络,你可以配置它,但是,所有的容器,都将使用同一个配置,比如 MTU 和 iptables 。额外的,配置默认桥接网络需要在 docker 外部完成,然后重启 docker。
    而用户定义的桥接网络,及其配置,都是通过指令 docker network create 完成的。不同的应用组可以使用不同的网络需求。

  • 在默认桥接网络上连接的容器共享环境变量
    起初,两个容器之间共享环境变量的唯一方式,是使用 --link 标识,而在用户定义的网络下,则无法通过这种方式共享变量。然而,其实还有一些其它较好的方式来完成环境变量共享:

  • 多个容器使用 Docker volumn 挂载同一个共享文件或者文件夹。

  • 使用 docker-compose 设置共享变量;

  • 使用 swarm serivce 代替单体的容器。

管理用户定义桥接网络

使用 docker network create 指令可以创建一个用户定义的桥接网络。

1
$ docker network create my-net

还可以指定子网、IP 段、网关等。可以通过 [docker network create]
(https://docs.docker.com/engine/reference/commandline/network_create/#specify-advanced-options) 或者 docker network create --help 获取详情。
删除时,使用:

1
$ docker network rm my-net

用户定义桥接网络的使用

创建一个容器时,可以指定一个或者多个 --network 标志。下面的例子,是将一个 Nginx 容器连接到 my-net 网络下,内部访问端口 80,外部访问端口 8080。任何连接到 my-net 网络的容器,都能访问到 my-nginx 容器,反之亦然了。

1
2
3
4
$ docker create --name my-nginx \
--network my-net \
--publish 8080:80 \
nginx:latest

如果一个正在运行的容器要连接到一个已经存在的用户定义桥接网络闪给,可以使用如下指令:

1
$ docker network connect my-net my-nginx

删除时:

1
$ docker network disconnect my-net my-nginx

使用默认的桥接网卡

默认桥接网络,是 Docker 的历史遗留问题,是不被推荐使用的。配置起来,很不方便,并且存在一些技术缺陷。

将容器连接到默认桥接网络中

如果不使用 --network flag,但是指定了网络驱动,你的容器就是连接在默认桥接网络上。在此网络内,容器只能通过 IP 相互访问,除非你使用 --link flag。

配置默认桥接网络

可以通过 deamon.json 配置默认桥接网络。以下是示例:

1
2
3
4
5
6
7
8
9
{
"bip": "192.168.1.5/24",
"fixed-cidr": "192.168.1.5/25",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}

重启 Docker 后生效。

####——–####

译者附

  1. docker compose 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #指定 docker-compose.yml 文件的写法格式
    version: "3.9" # optional since v1.27.0
    #多个容器的集合
    services:
    redist:
    build:
    context: ./
    dockerfile: Dockerfile
    ports:
    - "4631:9096"
    links: # 指定容器连接到当前连接,避免容器重启引发ip动态改变,无法连接
    - "db_redis"

    db_redis:
    image: redis
    container_name: db_redis
    ports:
    - "6679:6379"
    hostname: db_redis
  2. 使用 hostname 后,实际上:

  3. 项目练习地址

© 2024 YueGS