惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security Affairs
S
Schneier on Security
N
News | PayPal Newsroom
T
Threatpost
Cloudbric
Cloudbric
H
Heimdal Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Google Online Security Blog
Google Online Security Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Spread Privacy
Spread Privacy
V
Vulnerabilities – Threatpost
The Last Watchdog
The Last Watchdog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
L
LINUX DO - 最新话题
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
NISL@THU
NISL@THU
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The Hacker News
The Hacker News
O
OpenAI News
人人都是产品经理
人人都是产品经理
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Check Point Blog
C
Cisco Blogs
GbyAI
GbyAI
J
Java Code Geeks
L
LangChain Blog
I
Intezer
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
美团技术团队
The Register - Security
The Register - Security
Help Net Security
Help Net Security
WordPress大学
WordPress大学
Y
Y Combinator Blog
T
Tor Project blog
M
MIT News - Artificial intelligence
爱范儿
爱范儿
TaoSecurity Blog
TaoSecurity Blog
V
Visual Studio Blog
T
Threat Research - Cisco Blogs
P
Palo Alto Networks Blog
月光博客
月光博客
T
Tenable Blog
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
DataBreaches.Net

Liu Zijian's Blog | 一个技术博客

使用Certbot自动续签HTTPS证书 使用Filebeat采集Nginx日志到ES Python的协程 Python中的异常 Python中的类和对象 Python的函数 Python的数据结构,推导式、迭代器和生成器 Spring AI集成多模态模型 LangChain4j多模态 LangChain Tools工具使用 Python中的模块和包 Python全局环境和虚拟环境(venv) LangChain Prompt提示词工程 LangChain4j Tools工具使用 基于Dify搭建AI智能体应用 LangChain4j RAG检索增强生成 Spring AI实现MCP Server Spring AI集成MCP Client LangChain4j Prompt提示词工程 Spring AI使用知识库增强对话功能 Spring AI实现一个智能客服 Spring AI实现一个简单的对话机器人 实现MinIO数据的每日备份 自己实现一个DNS服务 简单理解AI智能体 大模型和大模型应用 LangChain开篇 LangChain4j开篇 一个解析Excel2007的POI工具类 DataPermissionInterceptor源码解读 TenantLineInnerInterceptor源码解读 BaseMultiTableInnerInterceptor源码解读 Spring AI开篇 SQL解析工具JSQLParser 芋道源码解读之多租户 芋道源码解读之数据权限 芋道源码解读开篇 Java实现将数据导出为Word文档 OA系统的天数该怎样计算 安装MySQL8 安装MySQL5.7 RockyLinux9环境下编译MySQL8 MySQL字符集及底层原理 Java实现LDAP登录 Docker Compose IPv4和IPv6 使用虚拟机安装一个K8s集群 使用GraalVM原生编译打包SpringBoot工程 Nginx防止目录穿越 Java线程的状态 Nginx防盗链设置 使用python将excel表格转换为SQL INSERT Redis的公共操作命令 Redis数据结构之Bitfleid Redis数据结构之Bitmap Redis数据结构之GEO Redis数据结构之Hash Redis数据结构之HyperLogLog Redis数据结构之List Redis数据结构之Set Redis数据结构之Stream Redis数据结构之String Redis数据结构之ZSet 使用python压缩图片 利用Python实现Hexo站点的持续集成 Nginx设置HTTPS监听 firewalld防火墙工具的使用 Linux信号(signal)机制 MySQL5.7x 主从复制 用IP自签发一个HTTPS证书 基于Hexo实现一个静态的个人博客 RockyLinux9环境下编译MySQL5.7 Docker离线安装 MySQL数据定义语言 Docker与联合文件系统 Docker的网络 Docker的镜像操作 MySQL存储过程 MyBatis-Plus开篇 MySQL变量 MySQL视图 MySQL事务 MySQL插入修改和删除 MySQL查询 MySQL系统命令 Docker的容器操作 Docker的安装和配置 Docker容器数据卷 浅谈OAuth2.0授权原理 JVM开篇 浅谈Linux(Unix)的I/O模型 一个通用的CloseableHttpClient工厂类 JUC可重入锁ReentrantLock JUC读写锁ReadWriteLock Java的单例 Java泛型 Java8的新特性 最近最少使用算法(LRU) MySQL函数 SpringBoot配置和启动
Docker的网络
Liu Zijian · 2024-01-24 · via Liu Zijian's Blog | 一个技术博客

Docker的网络用于容器间的互联和通信,以及宿主机端口映射,容器IP变动的时候可以设置网络直接使用服务名进行网络通信而不受影响。类似于虚拟机软件分配IP地址给各个安装的虚拟机以及物理机,虚拟机之间以及虚拟机和物理机之间可以相互通信。

1.查看容器的网络

1.查看容器网络类型

docker inspect命令查看关于Networks的部分

docker inspect 容器ID

当前容器是bridge网络,网关是172.17.0.1, IP是172.17.0.2

"Networks": {
              "bridge": {
                  "IPAMConfig": null,
                  "Links": null,
                  "Aliases": null,
                  "NetworkID": "2def63006d0705d822ebd7269baf1512be0fc886c40e9047f35635ef21585b33",
                  "EndpointID": "4fd79243a84032b34a57a39b0ffc03136bef175498980abdc097117e17f135fe",
                  "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
              }
          }

2.查看当前有多少个docker网络

docker network ls
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2def63006d07        bridge              bridge              local
f8b834999d26        host                host                local
fd9dc003ef95        lzjnet              bridge              local
2ca13d3f5552        none                null                local

3.查看网络的情况

docker network inspect 网络名

网络lzjnet的网络类型是bridge,还有IP等信息

[
    {
        "Name": "lzjnet",
        "Id": "fd9dc003ef956e7b3f01d74b81f5fc6cc04c76ce5144beadc9707dd4a7a41134",
        "Created": "2024-11-26T23:12:55.276879774+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

2.Docker的网络类型

几种常见的网络类型

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

2.1 bridge网络

1.主机和容器联网

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

2.容器之间联网

Docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关,因为在同一宿主机内的容器都接入同一网桥,这样容器之间就可以通过容器的Container-IP直接通信。

3.bridge网络的分配机制

docker run的时候,没有指定network的话,默认使用的网桥模式就是bridge(docker0)。在宿主机ifconfig就可以看见docker0和自己创建的网络(eth0, eth1…..),lo代表127.0.0.1。

网桥docker0创建一对对等的虚拟设备接口,一个叫veth,另一个叫eth0,成对匹配。

整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair)

每个容器内部也有一块网卡,每个接口叫eth0,docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。

验证veth-pair:

查看正在运行的Docker容器

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
38188376416b        tomcat              "catalina.sh run"   About a minute ago   Up About a minute   8080/tcp            inspiring_austin

宿主机执行ip addr查看宿主机的网络情况

[root@localhost ~]# 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:44:65:de brd ff:ff:ff:ff:ff:ff
    inet 192.168.228.104/24 brd 192.168.228.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::2ac6:ec4:9411:4da8/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ff:ca:bc:ec 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
    inet6 fe80::42:ffff:feca:bcec/64 scope link 
       valid_lft forever preferred_lft forever
15: vethc5f3f03@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 26:9a:2e:de:95:5a brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::249a:2eff:fede:955a/64 scope link 
       valid_lft forever preferred_lft forever

进入容器,一般需要先更新tomcat容器的yum,再安装工具iproute2

sudo apt-get update

sudo apt-get upgrade

apt-get install -y iproute2

然后,在容器内执行ip addr查看容器的网络情况

root@38188376416b:/# 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
14: eth0@if15: <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

然后可见宿主机的网卡 15: vethc5f3f03@if14 和容器网卡 14: eth0@if15两两匹配,互互相同

2.2 host网络

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

容器将不再获得一个独立的网络名称空间,而是和宿主机共用一个网络名称空间,容器将不会虚拟出自己的网卡,而是使用宿主机的IP和端口,容器没有自己的IP。

这种模式下,使用-p端口映射是无效的,也是没有任何意义的。

2.3 none网络

等同于禁用网络功能,不为容器进行任何网络配置,容器没有网卡,路由等信息,只有一个本地回环网卡lo

2.4 container网络

新建的容器和一个已经存在的容器共享一个网络IP配置而不是和宿主机共享,新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围等,同样,两个容器除了网络方面,其他的例如文件系统,进程列表等还是隔离的。

需要注意的是:

1.继承和被继承的容器的容器内端口不能是相同的,否则会导致冲突,因为两个容器共享网段和IP

验证:先启动一个tomcat容器tomcat86,该容器内的程序会占用容器的8080,在启动另一个tomcat容器tomcat87和前者共享网络,因为也是基于tomcat镜像,所以同样会占用容器的8080,两个容器端口范围是共享的,导致报错Error response from daemon: conflicting options: port publishing and the container type network mode.

docker run -d --privileged=true -p 8086:8080  --name tomcat86    tomcat

docker run -d --privileged=true -p 8086:8080 --network container:tomcat86  --name tomcat87    tomcat
[root@localhost ~]# docker run -d --privileged=true -p 8086:8080  --name tomcat86    tomcat
c8464b5448296b51bc5b4e4598acce709513aa6ac7fac6ef335e5a39e8a785f3
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
c8464b544829        tomcat              "catalina.sh run"   4 seconds ago       Up 2 seconds        0.0.0.0:8086->8080/tcp   tomcat86
0bad9102a5a7        alpine              "/bin/sh"           11 minutes ago      Up 11 minutes                                alpine1
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# docker run -d --privileged=true -p 8086:8080 --network container:tomcat86  --name tomcat87    tomcat
docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
See 'docker run --help'.

2.被继承的容器结束运行后,继承它的容器也会失去网络功能,只剩下一个回环网卡lo

验证:先运行一个精简版Linux容器alpine1,在运行一个同样的容器alpine2,指定和alpine1共享网络,查看容器内网络可见网卡名称和IP地址都是完全一样的

docker run -it --name alpine1   alpine /bin/sh
[root@localhost ~]# docker run -it --name alpine1   alpine /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
16: eth0@if17: <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
docker run -it --name alpine2 --network container:alpine1   alpine /bin/sh
[root@localhost ~]# docker run -it --name alpine2 --network container:alpine1   alpine /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
16: eth0@if17: <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

关闭容器alpine1,进入容器alpine2查看IP,发现eth网卡跟着消失了,只剩下lo

[root@localhost ~]# docker stop alpine1
alpine1
[root@localhost ~]# 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

2.5 自定义网络

为什么要自定义网络?

1.容器间的互联和通信以及端口映射
2.bridge模式网络分配给容器的IP是可能随着容器的启动关闭而导致分配的地址发生变动的,但是Docker自带的bridge网络比较简单,没有内置DNS功能,自定义网络后,容器IP变动的时候可以通过服务名直连网络而不受影响,当用户创建自定义网络时,Docker自动配置了一个内置DNS服务器,这个DNS服务器会根据容器的名称自动解析对应的IP地址。

自定义网络默认也是采用桥接模式bridge,只是功能比默认的那个更强,自然就维护好了容器名和IP的映射关系(DNS)

验证:

创建一个网络lzjnet

docker network create lzjnet

创建容器tomcat1 tomcat2,指定我们自己创建的网络,然后互PING

docker run -it --privileged=true  --network lzjnet   --name alpine81    alpine

docker run -it --privileged=true  --network lzjnet   --name alpine82    alpine
[root@localhost ~]# docker attach alpine81
/ # ping alpine82
PING alpine82 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.889 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.195 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.181 ms
64 bytes from 172.18.0.3: seq=3 ttl=64 time=0.167 ms
64 bytes from 172.18.0.3: seq=4 ttl=64 time=0.547 ms
^C
--- alpine82 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.167/0.395/0.889 ms
[root@localhost ~]# docker attach alpine82
/ # ping alpine81
PING alpine81 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.079 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.133 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.169 ms
64 bytes from 172.18.0.2: seq=3 ttl=64 time=0.186 ms
64 bytes from 172.18.0.2: seq=4 ttl=64 time=0.663 ms
64 bytes from 172.18.0.2: seq=5 ttl=64 time=0.260 ms
64 bytes from 172.18.0.2: seq=6 ttl=64 time=0.176 ms
^C
--- alpine81 ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max = 0.079/0.238/0.663 ms

可以发现可以使用容器名相互PING通

3.总结

Docker可以使用4种网络模式来实现容器之间以及和宿主机的网络通信,自己实现自定义的网络桥接模式功能更强。