从 01 开始 从 01 开始
首页
  • 计算机简史
  • 数字电路
  • 计算机组成原理
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • 数据库
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Node
  • Windows 使用技巧
  • 最全面的输入法教程
  • 浏览器
  • 终端软件
  • 装机
  • 笔记类软件
  • Markdown
  • 各大平台
  • 远程控制
  • RSS
  • 图片类工具
  • Office
  • 手机
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 教程简介
  • 英语学习方法论
  • 字母
  • 音标
  • 单词
  • 语法
  • 英语兔的相关视频
  • Larry 想做技术大佬的相关视频
  • 驾驶技能
  • 住房相关
  • 厨艺
  • 关于税
  • 理财
  • 睡眠
  • 皮肤
  • 口腔健康
  • 学会呼吸
  • 健身日志
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 反腐
  • GFW
  • 404 内容
  • 审查与自我审查
  • 互联网
  • 2022
  • 2023
  • 2024
  • 2025
  • 关于本站
  • 关于博主
  • 网站动态
  • 公告栏
  • 友人帐
  • 从零开始搭建一个博客
  • 搭建邮件服务器
  • 本站分享
  • 文章分类
  • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 计算机简史
  • 数字电路
  • 计算机组成原理
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • 数据库
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Node
  • Windows 使用技巧
  • 最全面的输入法教程
  • 浏览器
  • 终端软件
  • 装机
  • 笔记类软件
  • Markdown
  • 各大平台
  • 远程控制
  • RSS
  • 图片类工具
  • Office
  • 手机
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 教程简介
  • 英语学习方法论
  • 字母
  • 音标
  • 单词
  • 语法
  • 英语兔的相关视频
  • Larry 想做技术大佬的相关视频
  • 驾驶技能
  • 住房相关
  • 厨艺
  • 关于税
  • 理财
  • 睡眠
  • 皮肤
  • 口腔健康
  • 学会呼吸
  • 健身日志
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 反腐
  • GFW
  • 404 内容
  • 审查与自我审查
  • 互联网
  • 2022
  • 2023
  • 2024
  • 2025
  • 关于本站
  • 关于博主
  • 网站动态
  • 公告栏
  • 友人帐
  • 从零开始搭建一个博客
  • 搭建邮件服务器
  • 本站分享
  • 文章分类
  • 文章归档
  • 计算机历史

  • 数字电路

  • 计算机组成原理

  • 操作系统

  • Linux

    • Linux命令学习

    • 文本处理三剑客

    • 尚硅谷Docker实战教程

      • 教程简介
      • Docker 简介
      • Docker 安装
      • Docker 配置国内镜像源
      • Docker 常用命令
      • 镜像的分层概念
      • 发布镜像
      • Docker 私有库
      • 容器数据卷
      • Docker 常用软件安装
      • MySQL 主从复制
      • 分布式存储之哈希取余算法
      • 3 主 3 从Redis集群搭建与扩缩容
      • Dockerfile
      • 虚悬镜像
      • Docker 微服务实战
      • Docker 网络
        • 网络情况
        • 网络模式
        • 容器实例内默认网络 IP 生产规则
        • bridge
        • host
        • none
        • container
        • 自定义网络
        • link 技术
      • Docker-compose 容器编排
      • Portainer
      • Docker 重量级监控
      • Docker 系列完结
      • 记一次启动容器失败
    • Linux安全

  • 计算机网络

  • Git

  • 计算机小知识

  • 数据库

  • 计算机基础
  • Linux
  • 尚硅谷Docker实战教程
2023-09-18
目录

Docker 网络

# 150.Docker 网络

在之前讲 Redis 集群搭建的时候,我们用过一个选项 --net host​,现在就来讲讲该选项,以及 Docker 的网络。

‍

docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
1

‍

# 网络情况

我们先停止 Docker:systemctl stop docker​

在不启动 Docker 的情况下,网络情况是这样的:

$ ifconfig
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.242  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::3c89:876e:2930:5286  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:74:1d:cd  txqueuelen 1000  (Ethernet)
        RX packets 90493  bytes 13330101 (12.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 38633  bytes 3330369 (3.1 MiB)
        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 6230364  bytes 7704637318 (7.1 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6230364  bytes 7704637318 (7.1 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:06:12:45  txqueuelen 1000  (Ethernet)
        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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

‍

第一个 enp0s8,有一个 ip 地址 192.168.2.242,就是我们宿主机的地址

第二个 lo,就是 localhost 的简写,指本地回环链路;

第三个:virbr0,用的较少,了解即可。在虚拟机里,安装一个 Centos 的过程中,如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的 virbr0 网卡(virbr0 网卡还有一个固定的默认 IP 地址 192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。

之前学习 Linux 安装,勾选安装系统的时候附带了 libvirt 服务才会生成的一个东西,如果不需要可以直接将 libvirtd 服务卸载:yum remove libvirt-libs.x86_64​

‍

‍

docker 启动后,多了一个 docker0 的虚拟网桥:

$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c0ff:fe81:167e  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c0:81:16:7e  txqueuelen 0  (Ethernet)
        RX packets 57719  bytes 2948857 (2.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 60032  bytes 75842649 (72.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
1
2
3
4
5
6
7
8
9

‍

容器与容器之间、容器和宿主机之间,就是通过该虚拟网桥来通信的。

查看 docker 网络模式,这是安装 Docker 后,默认创建的:

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
5bd056a8204a   bridge    bridge    local
553d2c47bcaa   host      host      local
1ddfe19eb462   none      null      local
1
2
3
4
5

我们主要掌握前 2 个,第 3 个 none 很少用到。

‍

‍

我们看看文档:

$ docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

‍

‍

可以创建一个网络:

$ docker network create aa_network
9eeb4fd0bf15a59d77bdba7e40594eb30ddd2c2c2ad66df706608a939cd2d193


$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
9eeb4fd0bf15   aa_network   bridge    local
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local
1
2
3
4
5
6
7
8
9
10

NAME 为 bridge 的网络,是桥接模式;NAME 为 host 的是主机模式

‍

‍

查看网络源数据:docker network inspect XXX网络名字​

$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "Created": "2023-09-10T12:10:26.138357898+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

‍

‍

Docker 的网络能解决什么问题:

  • 容器间的互联和通信以及端口映射
  • 容器 IP 变动时,可以通过服务名直接网络通信而不受到影响

‍

访问一个容器,比较关键的一点是在不在同一网段。目前我们是在单机运行 Docker,所以这个问题不明显;

在工作中,则设计到多个 Docker,他们之间的网络管理和容器调用的规划,就得用到 Docker 网络的问题了

‍

# 网络模式

‍

网络模式 简介
bridge 为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0。虚拟网桥,默认是该模式
host 容器将不会虚拟出自己的网课,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none 容器有独立的 Network namespace,但并没有对其进行任何网络设置,
如分配 veth pair 和网桥连接,IP 等
container 新创建的容器不会创建自己的网卡和配置自己的 IP,
而是和一个指定的容器共享 IP、端口范围等

‍

  • bridge 模式:使用--network bridge 指定,默认使用 docker0。默认模式,最常见的模式
  • host 模式:使用--network host 指定
  • none 模式:使用--network none 指定,几乎不用
  • container 模式:使用--network container:NAME 或者容器 ID 指定

‍

‍

接下来我们通过一个实例,来理解为什么我们要学习这个 Docker 的网络知识

‍

# 容器实例内默认网络 IP 生产规则

先启动两个 ubuntu 容器实例:

$ docker run -it --name u1 ubuntu 

$ docker run -it --name u2 ubuntu 

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
3e1c46b6b32e   ubuntu    "bash"    8 seconds ago    Up 7 seconds              u2
64fecffbfaca   ubuntu    "bash"    26 seconds ago   Up 25 seconds             u1
1
2
3
4
5
6
7
8

‍

接下来查看下容器内的信息:docker inspect u1​,最后面有网络的信息:

"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "9b0b1229700e53ea0651dd347d599d3873fa6f00ad92e255c72c2c17fabc87e8",
        "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
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

可以看到目前是桥接模式,网关是 172.17.0.1,容器本身的 IP 是 172.17.0.2

‍

u2 的信息:

"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "3acf96d0214c8bb088e615e5e0544f19527e7da4fe8dd2cf57dee9f4f72c8ef0",
        "Gateway": "172.17.0.1",
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:11:00:03",
        "DriverOpts": null
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

‍

‍

如果我们删除 u2 实例,再启动一个新的 u3,并查看其休息:

$ docker rm -f u2


$ docker run -it --name u3 ubuntu 


$ docker inspect u3
 "Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "371217a338a6787dd444ebd315fe5fee14b6346d2dd90601bcc49a29b7ecdfda",
        "Gateway": "172.17.0.1",
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:11:00:03",
        "DriverOpts": null
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

‍

可以看到 u3 的 IP,和之前 u2 的一样。如果我们想要 u2 的服务,结果 u2 被删除了,请求发到 u3 了,那么可能就会出错。

结论:docker 容器内部的 ip 是有可能会发生改变的。

为此,有必要自己做一些网络设计,例如创建一个新的网络模式,让部分容器在该网络模式下运行。

‍

‍

# bridge

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为 docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。示意图:

​​

‍

说明:

  • Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
  • docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。在宿主机 ifconfig,就可以看到 docker0 和自己 create 的 network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo 代表 127.0.0.1,即 localhost,inet addr 用来表示网卡的 IP 地址
  • 网桥 docker0 创建一对对等虚拟设备接口一个叫 veth,另一个叫 eth0,成对匹配。
    • 整个宿主机的网桥模式都是 docker0,类似一个交换机有一堆接口,每个接口叫 veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫 veth pair);
    • 每个容器实例内部也有一块网卡,每个接口叫 eth0;
    • docker0 上面的每个 veth 匹配某个容器实例内部的 eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的 ip,此时两个容器的网络是互通的。

​​

接下来我们两两匹配验证,启动两个 Tomcat:

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8
1
2

‍

然后我们可以用 ip addr 命令查看,在下方多了两个 veth 的:

61: veth6ddaa35@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether e6:d2:ee:03:d7:7e brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::e4d2:eeff:fe03:d77e/64 scope link 
       valid_lft forever preferred_lft forever


63: veth6b10f89@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether fa:f7:44:71:39:65 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::f8f7:44ff:fe71:3965/64 scope link 
       valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9
10

‍

‍

进入到容器内部,可以看到有 eth0 的:

$ docker exec -it tomcat81 bash


$ ip addr
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

60: eth0@if61: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9
10
11
12
13

‍

可以看到 eho0 和 veth 是一一配对的,

‍

‍

接下来介绍下 host 模式。

# host

host,主机模式,直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行 NAT 转换。

容器将不会获得一个独立的 Network Namespace, 而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的 IP 和端口。示意图:

​​

‍

‍

再启动一个 Tomcat:可以看到有一个警告,不太推荐该种模式

$ docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8
WARNING: Published ports are discarded when using host network mode
09a334d59bc97365d886911be278ebcd9e4dff637dcda97a6687fe3e9b1d2335
1
2
3

‍

为什么有警告?docker 启动时指定--network=host 或-net=host,如果还指定了-p 映射端口,那这个时候就会有此警告,并且通过-p 设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。

解决的办法就是使用 docker 的其他网络模式,例如--network=bridge;或者不用-p 选项,或忽略警告

‍

此时我们用 docker inspect tomcat83 ​查看信息:没有网关和 IP 地址。

"Networks": {
    "host": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "553d2c47bcaad9d82904e56225e6afae3d5a23379822c9d96ac74170041aad79",
        "EndpointID": "1946b0286e008731cb65b6a30f074d6995dc08936126029bb76ea4665dd3d446",
        "Gateway": "",
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "",
        "DriverOpts": null
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

‍

进入容器内部看:几乎和宿主机的一样

$ docker exec -it tomcat83 bash

$ ip addr
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: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:a4:2c:88 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic enp0s3
       valid_lft 84224sec preferred_lft 84224sec
    inet6 fe80::d81a:24b:f174:82f/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:74:1d:cd brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.242/24 brd 192.168.2.255 scope global noprefixroute dynamic enp0s8
       valid_lft 602624sec preferred_lft 602624sec
    inet6 fe80::3c89:876e:2930:5286/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:06:12:45 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever


5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:06:12:45 brd ff:ff:ff:ff:ff:ff



6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:94:6e:78:c1 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

‍

‍

‍

‍

没有设置-p 的端口映射了,如何访问启动的 tomcat83 ?直接访问宿主机即可!http://宿主机 IP:8080/

在 CentOS 里面用默认的火狐浏览器访问容器内的 tomcat83 看到访问成功,因为此时容器的 IP 借用主机的,所以容器共享宿主机网络 IP,这样的好处是外部主机与容器可以直接通信。

​​

‍

‍

# none

在 none 模式下,并不为 Docker 容器进行任何网络配置,禁用了网络功能,只有 lo 标识(就是 127.0.0.1,本地回环)

也就是说,这个 Docker 容器没有网卡、IP、路由等信息,只有一个 lo,需要我们自己为 Docker 容器添加网卡、配置 IP 等。

‍

‍

启动一个来分析:

docker run -d -p 8084:8080 --network none --name tomcat84 billygoo/tomcat8-jdk8
1

‍

‍

通过 inspect 查看:没有网关和 IP

$ docker inspect tomcat84 | tail -n 20
"Networks": {
    "none": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "1ddfe19eb462f6485c00ec56945ce5d1835d4aac20b6229e73a0018176c05ff5",
        "EndpointID": "9b92af07ef5c8c85a0c1218167304a72ac01047af69be44e489d199e1879d260",
        "Gateway": "",
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "",
        "DriverOpts": null
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

‍

进入容器内看:

$ docker exec -it tomcat84 bash


$ ip addr
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
1
2
3
4
5
6
7
8

‍

了解即可,不过多展开

‍

‍

# container

新建的容器和已经存在的一个容器共享一个网络 IP 配置而不是和宿主机共享。

新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同

样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

示意图:

​​

‍

‍

接下来实践下,先创建一个容器:

docker run -d -p 8085:8080 --name tomcat85 billygoo/tomcat8-jdk8
1

‍

然后创建第二个,并使用第一个容器的网卡,但是报错了:

$ docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8
$ docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
See 'docker run --help'.
1
2
3

相当于 tomcat86 和 tomcat85 公用同一个 ip 同一个端口,导致端口冲突

‍

‍

这里我们换个镜像:Alpine 操作系统。Alpine Linux 是一款面向安全的、轻型、独立的、非商业的通用 Linux 发行版,专为追求安全性、简单性和资源效率的用户而设计。 可能很多人没听说过这个 Linux 发行版本,但是经常用 Docker 的朋友可能都用过,因为他小,简单,安全而著称,所以作为、基础镜像是非常好的一个选择,可谓是麻雀虽小但五脏俱全,镜像非常小巧,不到 6M 的大小,所以特别适合容器打包

启动 2 个容器:

docker run -it                             --name alpine1  alpine /bin/sh
1

‍

新开一个终端,运行第二个:

docker run -it --network container:alpine1 --name alpine2  alpine /bin/sh
1

‍

接下来验证是否共用搭桥,在两个终端内执行 ip addr​:

$ docker exec -it alpine1 /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9
10

‍

‍

$ docker exec -it alpine2 /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9
10

‍

可以看到两个 IP 都是一样的,172.17.0.2。如果 alpine1 被关闭了呢?docker stop alpine1​

‍

那么 alpine2 也没有 IP 了:

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
1
2
3
4
5

‍

‍

‍

# 自定义网络

接下来介绍第 5 种:自定义网络

Docker 默认的网络有 3 种:

$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local
1
2
3
4
5

‍

‍

但是我们也可以创建一个网络:

$ docker network create aa_network
9eeb4fd0bf15a59d77bdba7e40594eb30ddd2c2c2ad66df706608a939cd2d193


$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
9eeb4fd0bf15   aa_network   bridge    local
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local
1
2
3
4
5
6
7
8
9
10

‍

为什么需要自定义网络?可以将容器分门别类,在各自的网络中通信。之前我们演示过,Docker 内容器的 IP 是有可能发生变化的

‍

在介绍自定义网络之前,我们再次演示下,不使用自定义网络有什么问题。

为避免干扰,先删除其他容器,再启动两个 Tomcat:

docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8
1
2

‍

然后我们打开两个终端,分别进入容器:

docker exec -it tomcat81 bash
docker exec -it tomcat82 bash
1
2

‍

‍

81 的 IP 信息:172.17.0.2

$ ip addr
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
23: eth0@if24: <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
1
2
3
4
5
6
7
8
9

‍

‍

82 的 IP 信息:172.17.0.3

$ ip addr
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
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9

‍

‍

此外,在两个容器内,互相是能 ping 通的,例如 81 能 ping 通 82:

$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.024 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.024 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.026 ms
1
2
3
4
5
6

‍

既然 IP 地址是可能变化的,那么根据 IP 地址来通信是可能会被干扰的,能否通过服务名来 ping 呢?当然是不行的,例如在 81:

$ ping tomcat2
ping: tomcat2: Name or service not known
1
2

‍

‍

接下来我们演示,使用自定义网络的话,能不能解决上述问题。

首先自定义桥接网络,自定义网络默认使用的是桥接网络 bridge:

$ docker network create zzyy_network

$ docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
f1c9ebe5d961   bridge         bridge    local
553d2c47bcaa   host           host      local
1ddfe19eb462   none           null      local
daf309d234de   zzyy_network   bridge    local
1
2
3
4
5
6
7
8

‍

‍

删除之前的容器,新建容器,加入上一步新建的网络:

docker run -d -p 8081:8080 --network zzyy_network  --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network zzyy_network  --name tomcat82 billygoo/tomcat8-jdk8
1
2

‍

‍

‍

再次打开两个终端,分别进入容器,,并且试试能否 ping 通:

$ docker exec -it tomcat81 bash

$ ping tomcat82
PING tomcat82 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=3 ttl=64 time=0.039 ms
1
2
3
4
5
6
7

‍

可以看到完全能 ping 通。

结论:自定义网络本身就维护好了主机名和 IP 的对应关系( IP 和域名都能通)

‍

‍

‍

# link 技术

在过去,Docker 还有一种通信的功能(类似网络),叫做 link,不过已经过时了,不用再去学习,官网文档如下:Legacy container links (opens new window)

The --link​ flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link​.

.......

‍

(完)

上次更新: 2024/8/30 08:54:46
Docker 微服务实战
Docker-compose 容器编排

← Docker 微服务实战 Docker-compose 容器编排→

最近更新
01
2025 年 2 月记
02-28
02
最全面的浏览器教程-完结撒花
02-16
03
这个工具可以轻松搞到你的浏览器账户密码!
02-15
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式