一. Docker 容器的网络模式
当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 的网络模式非常丰富,可以满足不同容器的通信要求,下表列出了这些网络模式的主要信息
网络模式 | 创建此种网络模式的关键选项 | 简单说明 |
---|---|---|
host 模式 | –network host | 容器直接使用宿主机的网络栈,没有独立的网络命名空间,网络性能高,但容器与宿主机共享网络资源,易出现端口冲突 |
container 模式 | –network container:<已有容器名或 ID> | 新容器共享指定已有容器的网络命名空间,两个容器网络配置相同,适用于需要紧密耦合通信的容器组合 |
none 模式 | –network none | 容器仅有一个 1o 回环接口,无任何外部网络连接,适用于对网络安全性要求极高或需手动配置网络的场景 |
bridge 模式 | 默认模式,可通过-d bridge 手动指定(一般省略) | Docker 默认网络模式,创建 docker8 虚拟网桥,容器通过 veth 设备连到该网桥,容器有独立IP,借助宿主机NAT 访问外部网络 |
Overlay 模式 | -d overlay | 用于 Docker Swarm 集群,基于 VXLAN 技术创建跨主机的虚拟覆盖网络,实现不同宿主机上容器间的通信 |
macvlan 模式 | -d macvlan,还需指定–subnet、–gateway 和-o parent=<宿主机物理网卡> | 为容器分配唯一 MAC 地址,使其像独立物理设备,直接连接宿主机物理网络接口,绕过 docker0 网桥,提高网络性能 |
自定义网络模式 | docker network create 结合如–subnet、–gateway、–ip-range 等参数 | 用户可根据需求灵活配置网络参数,如子网、网关、IP 范围等,创建符合特定要求的网络 |
1. Bridge 模式
当 Docker 安装完成后,会自动创建一个名为 docker8 的虚拟网桥。在 Bridge 模式下,新创建的容器会通过一个虚拟以太网设备对(veth pair)连接到 dockerg 网桥上
Docker 守护进程会从预定义的子网中为每个容器分配一个唯一的 IP 地址。容器可以通过 dockere网桥与宿主机以及其他连接到该网桥的容器进行通信
当容器需要访问外部网络时,宿主机的内核会通过网络地址转换(NAT)将容器的私有 IP 地址转换为宿主机的公共 IP 地址,从而实现容器与外部网络的通信
bridge 模式是 docker 的默认网络模式,不写-net 参数,就是 bridge 模式。使用 docker run -p时,docker 实际是在 iptables 做了 DNAT 规则,实现端口转发功能。可以使用 iptables -t nat -vnl查看。bridge 模式如下图所示:
如果你之前有 Docker 使用经验,你可能已经习惯了使用–link 参数来使容器互联
随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数
(1)创建一个叫 mynet 的 bridge 类型的网络
[root@localhost ~]# docker network create -d bridge mynet
(2)查看都有哪些网路
[root@localhost ~]# docker network ls
(3)运行一个容器并连接到新建的 mynet 网络
[root@localhost ~]# docker run -dit --rm --name busy1 --network mynet busybox sh -c 'while true;do echo hello;done'
[root@localhost ~]# docker ps -a
[root@localhost ~]# docker logs 12
(4)运行一个容器并加入到 mynet 网络
[root@localhost ~]# docker run -it --rm --name busy2 --network mynet busybox sh
/ # ping busy1
2. Host 模式
使用 Host 模式的容器会直接使用宿主机的网络栈,容器没有独立的网络命名空间,而是与宿主机共享相同的 IP 地址、端口等网络资源
由于容器和宿主机共享网络栈,因此容器可以直接使用宿主机的网络接口,不存在网络地址转换和网桥转发的开销,网络性能较高。但同时也意味着容器之间以及容器与宿主机之间的网络隔离性较差,可能会出现端口冲突等问题
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。 Host模式如下图所示:
由于使用了 Host 模式,容器会直接使用宿主机的网络端口,因此可以直接在宿主机上通过 localhost访问容器内的服务,使用 ifconfig 命令可以看到容器的网络和宿主机的是一致的
[root@localhost ~]# docker run -dit --net=host --name host1 busybox
[root@localhost ~]# docker exec -it host1 sh
/ # ifconfig
3. Coneainer 模式
Container 模式允许一个容器共享另一个容器的网络命名空间,即两个容器使用相同的网络配置,包括 IP 地址、端口等,利用这种模式使得容器共享统一的网络命名空间
这种模式适用于那些需要紧密耦合的容器,例如一个应用程序和它的日志收集器容器,它们可以共享同一个网络,方便进行通信和数据传输
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 P,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 10网卡设备通信。 Container 模式示意图:
[root@localhost ~]# docker run -dit --name Chost1 busybox
[root@localhost ~]# docker run -dit --net=container:Chost1 --name Chost2 busybox
[root@localhost ~]# docker exec -it Chost1 sh
/ # ifconfig
[root@localhost ~]# docker exec -it Chost2 sh
/ # ifconfig
创建Chost2容器共享Chost1容器的网络
查询Chost1的网络
查询Chost2的网络,网络一致
4. None 模式
在 None 模式下,容器只有一个 10 回环接口,没有任何外部网络连接。这种模式适用于那些不需要网络通信或者需要手动配置网络的场景,例如某些安全敏感的 应用程序
如果需要为 None 模式的容器添加网络功能,需要手动创建网络接口并进行配置
使用 none 模式,Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。 None 模式示意图:
[root@localhost ~]# docker run -dit --net=none --name none01 busybox sh
[root@localhost ~]# docker exec -it none01 sh
/ # ifconfig
5. Overlay 模式
overlay 模式主要用于 Docker Swarm 集群,它允许容器在不同的 Docker 宿主机之间进行通信它基于 VXLAN(Virtual extensible Local Area Network)技术,在物理网络之上创建一个虚拟的覆盖网络
当容器之间进行通信时,数据包会被封装在 VXLAN 报头中,通过物理网络进行传输。在接收端,VXLAN报头会被解封装,还原出原始的数据包
0verlay 网络是分布式的,每个Docker宿主机上都有一个网络代理(如Docker的 docker_gwbridge)负责管理和转发数据包
6. Macvlan 模式
在 Macvlan 模式下,Docker 为每个容器分配一个唯一的 MAC 地址,使得容器在网络中看起来像个独立的物理设备
容器直接连接到宿主机的物理网络接口,终过了 docker8 网桥,从而提高了网络性能。容器可以直接与外部网络进行通信,就像一个独立的主机一样
每个容器都有自己独立的网络配置,与宿主机和其他容器之间相互隔离
[root@localhost ~]# docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o patent=ens160 mac-net
[root@localhost ~]# docker run -dit --name mac-net-c --network mac-net busybox
[root@localhost ~]# docker exec -it mac-net-c sh
/ # ifconfig
创建一个网络
创建一个使用网络的容器
查看网络
7. 自定义网络模式
除了上述内置的网络模式,你还可以使用 docker network create 命令创建自定义的 bridge 网络,以满足特定的网络需求,例如指定子网、网关、IP 范围等
此命令的主要目的是创建一个新的 Docker 网络,这个网络可以用于容器之间的通信。默认情况下,创建的是一个基于 bridge 驱动的网络
[root@localhost ~]# docker network create --subnet=192.168.2.0/24 --gateway=192.168.2.1 zidongyi
[root@localhost ~]# docker run -dit --name contain --network zidongyi busybox
[root@localhost ~]# docker exec -it contain sh
/ # ifconfig
- docker network create:这是 Docker 提供的用于创建网络的基础命令
- –subnet=172.21.0.0/16:指定了该网络使用的子网范围。172.21.0.0/16 是一个 CIDR(无类别域间路由)表示法,意味着该子网的网络地址是 172.21.0.0,子网掩码为 255.255.0.0可以容纳 65534 个可用的IP 地址(2^(32 - 16)-2,减去网络地址和广播地址)。当容器连接到这个网络时,它们将从这个子网范围内分配IP 地址
- –gateway=172.21.0.1:设置了该网络的网关地址。网关是容器访问外部网络(超出该子网范围)的出口点。当容器需要与子网外的网络进行通信时,数据包会被发送到这个网关地址进行转发。
- my__custom_network:为新创建的网络指定了一个名称,后续在创建容器时,可以通过这个名称将容器连接到该网络
二. 端口映射
Docker 是一个开源的容器化平台,用于构建、运行和管理应用程序。它使用容器来打包应用程序及其依赖项,使得应用程序可以在不同的环境中快速、可靠地运行。在 Docker 中,端口映射是一个重要的特性,它允许容器内部的应用程序与宿主机进行通信
Docker 的端口映射使用-p或–publish选项来实现。通过该选项,可以将容器内部的端口映射到宿主机上的某个端口。这样,容器内部的应用程序可以通过宿主机的端口来访问外部的网络或服务。宿主机上的端口号,表示容器内部的端口号。通过指定这两个端口号,Docker 会将容器内部的端口映射到宿主机的端口上
1. 端口映射
(1)-P(大写):指的是容器应用 PORT 随机映射到宿主机上的PORT
- 自动绑定所有对外提供服务的容器端口,映射的端口将会从没有使用的端口池中自动随机选择,但是如果连续启动多个容器的话,则下一个容器的端口默认是当前容器占用端口号+1
- 生产场景一般不使用随机映射,好处是由 docker 分配,宿主机端口不会冲突
(2)-p(小写):(宿主机 PORT:容器 PORT)
- 宿主机 IP 不写表示“0.0.0.0”,宿主机 PORT 不写表示随机端口,容器 PORT 必须指定,可以同时对多个端口进行映射绑定
- 指定端口映射,在标准化场景下使用频率高
- 端口的取值范围 32768–61000 之间
2. 随机映射端口
在使用 docker run 命令创建并启动容器时,可以使用 --P(大写的 P)参数来实现随机端口映射。它会将容器中 EXPOSE 指令声明的所有端口随机映射到宿主机的可用端口上
假设你要运行一个 Nginx 容器,Nginx 默认监听 80 端口。使用以下命令启动容器
[root@localhost ~]# docker run --rm -d -P nginx
[root@localhost ~]# docker ps -a
在 docker run --rm 命令中,–rm 是一个组合的选项,并不是r 和 m 分别代表不同含义,它是个整体参数,用于控制容器在停止运行后自动删除
当你在运行容器时添加 --rm 选项,Docker 会在容器退出时自动删除该容器的文件系统和所有相关资源,这样可以避免产生大量不再使用的容器,节省磁盘空间
3. 指定映射端口
docker run 命令用于创建并启动一个新的容器,通过 -p(小写的 p)参数可以指定容器端口到主机端口的映射
(1)固定端口
假设你要运行一个 Nginx 容器,并将容器的 80 端口映射到宿主机的 8080 端口,可使用以下命令:
[root@localhost ~]# docker run --rm -d -p 8080:80 nginx
[root@localhost ~]# docker ps -a
需要注意的是,在映射端口时,所使用的 docker 主机上的端口不能与其他容器或程序的端口冲突否则,容器无法正常创建
(2)宿主机随机端口
当使用小写的 -p 参数时,你可以不指定宿主机的具体端口,只给出容器端口,Docker 会自动将容器端口映射到宿主机的一个随机可用端口上
[root@localhost ~]# docker run --rm -d -p 80 nginx
[root@localhost ~]# docker ps -a
三. 容器互联
在 Docker 环境中,每个容器默认情况下是相互隔离的,它们有自己独立的网络栈。容器互联就是打破这种隔离,让不同容器能够识别彼此并进行网络通信,就像它们处于同一个本地网络中一样。通过容器互联,一个容器可以像访问本地网络中的其他设备一样访问另一个容器提供的服务,比如访问另一个容器运行的数据库、web 服务等
更用–link 选项(已逐渐被弃用)
在早期的 Docker 版本中,–link 选项用于实现容器互联。它允许一个容器通过别名来访问另一个容器。接下来介绍其实现步骤
1. 创建源容器
[root@localhost ~]# docker run -dit --name web01 centos:7
2. 创建接收容器
[root@localhost ~]# docker run -dit --name web02 --link web01:myweb01 centos:7
3. 测试容器互联
[root@localhost ~]# docker exec -it web02 bash
[root@9175a702d5c0 /]# cat /etc/hosts
四. 容器间通信实现案例
由于 --link 选项已逐渐被弃用,建议使用 Docker 网络来实现容器互联。docker networkcreate 是 Docker 提供的一个用于创建自定义网络的命令。在 Docker 中,网络用于容器之间的通信以及容器与外部世界的通信
创建自定义网络
创建一个不在此网络的容器
创建两个并加入自定义网络
测试通信
五. Docker 的数据管理
Docker 数据卷(Data Volumes)是 Docker 中用于持久化存储数据的一种机制,它在容器和宿主机之间建立了一种数据共享的方式
下面从多个方面详细解释 Docker 数据卷
1. 什么是数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过了容器的文件系统,直接将宿主机上的目录或文件挂载到容器内部。这意味着即使容器被删除,数据卷中的数据也不会丢失,从而实现了数据的持久化存储
2. 数据卷的作用
(1)数据持久化
容器的生命周期可能是短暂的,当容器被删除时,其内部文件系统中的数据也会随之消失。而数据卷可以将数据存储在宿主机上,确保数据不会因为容器的删除而丢失
(2)数据共享
多个容器可以同时挂载同一个数据卷,从而实现容器之间的数据共享。这对于需要共享配置文件、日志文件或其他数据的应用场景非常有用
(3)数据备份和恢复
由于数据卷中的数据存储在宿主机上,因此可以方便地进行备份和恢复操作
(4)分离数据和应用
将数据存储在数据卷中,可以使容器的镜像更加轻量级,只包含应用程序本身,而将数据分离出来,提高了容器的可移植性和可维护性
3. 创建匿名数据卷
在创建容器时,可以使用-v或-volume 参数来创建和挂载匿名数据卷
上述命令创建了一个名为 web04 的容器,并在容器内部创建了一个 /data1 目录和/data2 目录作为数据卷。Docker 会自动在宿主机上的/var/lib/docker/volumes 目录下分配一个该容器的目录来存储这个数据卷的数据。主当把此容器删除掉以后,宿主机上的目录以及里面的数据仍然存在。可登录到此容器验证这一效果
4. 创建具名数据卷
具名数据卷是一种有名称的数据卷,可以更方便地管理和使用
创建具名数据卷
创建容器时挂载具名数据卷
5. 共享容器数据卷
容器之间共享数据
这个命令的主要功能是基于 centos:7 镜像创建并启动一个名为 web05 的新容器,该容器会以交互模式、守护进程模式运行,并且会从web04容器中挂载所有的数据卷。-volumes-from web4:这是一个关键参数,它的作用是让新创建的 web05 容器挂载 web04 容器中所有已经挂载的数据卷。这意味着 webe5 容器可以访问和使用 webe4 容器所使用的数据卷中的数据实现数据的共享
注意事项:
如果 web04 容器被删除,只要数据卷本身没有被删除,web05 容器仍然可以正常访问数据卷中的数据
当多个容器共享同一个数据卷时,对数据卷中数据的修改会影响到所有挂载该数据卷的容器
6. 挂载主机目录作为数据卷
可以将宿主机上的指定目录挂载到容器内部,实现数据的共享
创建目录
准备数据
创建数据
六. Docker 数据管理注意事项
在 Docker 中进行数据管理时,需要考虑数据的持久化、共享、备份、恢复以及安全性等多个方面
1. 明确使用场景选择类型
匿名数据卷创建简单,但管理不便,适合临时存储中间数据。例如在构建过程中存储临时编译文件
具名数据卷便于管理和共享,适用于需要持久化存储且后续会频繁使用的数据
如数据库数据挂载主机目录数据卷则方便与主机进行数据交互,适合需要与主机共享配置文件或数据的场景。
2. 使用正确的路径
挂载主机目录作为数据卷时,必须使用绝对路径,否则会导致挂载失败
3. 数据卷清理
定期清理无用数据卷:使用 docker volume ls 查看所有数据卷,对于不再使用的匿名或具名数据卷,使用 docker volume rm 命令进行清理,避免占用过多磁盘空间
4. 容器内数据持久化
容器的文件系统是基于镜像层和容器层构建的,容器层的数据在容器删除时会丢失。因此,对于需要持久化的数据,应使用数据卷进行存储
多个容器可以挂载同一个数据卷来实现数据共享。但要注意并发访问问题,可能需要在应用层面实现数据同步机制,如使用锁机制或事务处理
对于数据库、日志文件等关键数据,应将其存储在数据卷中,确保数据的持久化和可恢复性.例如,对于 MySQL 容器,将数据目录 /var/lib/mysql 挂载到数据卷上