容器通信技术与数据持久化
目录
第一节:容器通信技术
一:Docker容器的网络模式
1:Bridge模式
2:host模式
3:Container模式
4:none模式
5:overlay模式
6:macvlan模式
7:自定义网络模式
二:端口映射
1:随机映射端口
2:指定映射端口
(1)固定端口
(2)宿主机随机端口
三:容器互联
1:使用--link选项
四:容器间通信实现案例
1:常用选项及解释
2:容器间通信步骤
第二节:数据持久化技术
一:Docker的数据管理
1:什么是数据卷
2:数据卷的作用
3:创建匿名数据卷
4:创建具名数据卷
(1)创建具名数据卷
(2)在创建容器时挂载具名数据卷
5:共享容器数据卷
6:挂在主机目录作为数据卷
二:Docker数据管理注意事项
第一节:容器通信技术
一:Docker容器的网络模式
当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 的网络模式非常丰富,可以满足不同容器的通信要求,下表列出了这些网络模式的主要信息。
网络模式 | 创建此种网络模式的关键选项 | 简单说明 |
---|---|---|
host 模式 | --network host | 容器直接使用宿主机的网络栈,没有独立的网络命名空间,网络性能高,但容器与宿主机共享网络资源,易出现端口冲突。 |
container 模式 | --network container:<已有容器名或 ID> | 新容器共享指定已有容器的网络命名空间,两个容器网络配置相同,适用于需要紧密耦合通信的容器组合。 |
none 模式 | --network none | 容器仅有一个 lo 回环接口,无任何外部网络连接,适用于对网络安全性要求极高或需手动配置网络的场景。 |
bridge 模式 | 默认模式,可通过 -d bridge 手动指定(一般省略) | Docker 默认网络模式,创建 docker0 虚拟网桥,容器通过 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 安装完成后,会自动创建一个名为 docker0 的虚拟网桥。在 Bridge 模式下,新创建的容器会通过一个虚拟以太网设备对(veth pair)连接到 docker0 网桥上。
Docker 守护进程会从预定义的子网中为每个容器分配一个唯一的 IP 地址。容器可以通过 docker0 网桥与宿主机以及其他连接到该网桥的容器进行通信。
当容器需要访问外部网络时,宿主机的内核会通过网络地址转换(NAT)将容器的私有 IP 地址转换为宿主机的公共 IP 地址,从而实现容器与外部网络的通信。
bridge 模式是 docker 的默认网络模式,不写 -net 参数,就是 bridge 模式。使用 docker run -p 时,docker 实际是在 iptables 做了 DNAT 规则,实现端口转发功能。可以使用 iptables -t nat -vnL 查看。
#创建一个叫my-net的bridge类型网络
docker network create -d bridge my-net
#列出docker中的网络
docker network ls
#运行一个容器并连接到新建的my-net网络
docker run -dit --name busybox1 --rm --network my-net busybox sh -c "while true;do echo nihao;done"//busybox1:镜像名称
//--rm:当容器运行时删除这个指令
//sh:调用shell解释器
//-c:conmod命令#运行一个容器并加入到my-net网络
docker run -it --name busybox2 --rm --network my-net busybox sh
进入后:
/ # ping busybox1
/ # ping www.baidu.com #测试与外网连接
2:host模式
使用 Host 模式的容器会直接使用宿主机的网络栈,容器没有独立的网络命名空间,而是与宿主机共享相同的 IP 地址、端口等网络资源。
由于容器和宿主机共享网络栈,因此容器可以直接使用宿主机的网络接口,不存在网络地址转换和网桥转发的开销,网络性能较高。但同时也意味着容器之间以及容器与宿主机之间的网络隔离性较差,可能会出现端口冲突等问题。
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace,容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
#创建一个叫my-net1的host类型网络
docker network create -d host my-net1
(只能创建一个仅主机的模式)
#运行一个容器并连接到新建的my-net1网络
docker run -dit --net=host --name docker_host1 busybox
docker ps
#登录终端
docker exec -it docker_host1 sh
进入后:
/ # ifconfig
/ # ping www.baidu.com #测试与外网连接
3:Container模式
Container 模式允许一个容器共享另一个容器的网络命名空间,即两个容器使用相同的网络配置,包括 IP 地址、端口等,利用这种模式使得容器共享统一的网络命名空间。
这种模式适用于那些需要紧密耦合的容器,例如一个应用程序和它的日志收集器容器,它们可以共享同一个网络,方便进行通信和数据传输。
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
#创建一个叫host1的Container类型网络
docker run -dit --name host1 busybox
#创建hosts容器共享host1容器的网络
docker run -dit --net=container:host1 --name host2 busybox
#查询host1容器的网络
docker exec -it host1 ifconfig
#查询host2容器的网络
docker exec -it host2 ifconfig
(确认与host1容器的网络一致)
4:none模式
示例:
#创建一个叫none01的none类型网络
docker run -dit --net=none --name none01 busybox sh
#登录终端
docker exec -it none1 sh
进入后:
/ # ifconfig
5:overlay模式
Overlay 模式主要用于 Docker Swarm 集群,它允许容器在不同的 Docker 宿主 机之间进行通信。它基于 VXLAN(Virtual eXtensible Local Area Network)技术,在物理网络之上创建一个虚拟的覆盖网络。
当容器之间进行通信时,数据包会被封装在 VXLAN 报头中,通过物理网络进行传输。在接收端,VXLAN 报头会被解封装,还原出原始的数据包。
Overlay 网络是分布式的,每个 Docker 宿主机上都有一个网络代理(如 Docker 的 docker_gwbridge)负责管理和转发数据包。
#在 Docker Swarm 集群中创建一个 Overlay 网络
docker network create -d overlay my_overlay_network#在不同的宿主机上创建服务并连接到 Overlay 网络
docker service create --name my_service --network my_overlay_network nginx
6:macvlan模式
在 Macvlan 模式下,Docker 为每个容器分配一个唯一的 MAC 地址,使得容器在网络中看起来像一个独立的物理设备。
容器直接连接到宿主机的物理网络接口,绕过了 docker0 网桥,从而提高了网络性能。容器可以直接与外部网络进行通信,就像一个独立的主机一样。
每个容器都有自己独立的网络配置,与宿主机和其他容器之间相互隔离。
示例:使容器获得一个与宿主机在同一子网内的 IP 地址,可以直接与外部网络进行通信。
#创建一个 Macvlan 网络
docker network create -d macvlan
--subnet=192.168.1.0/24
--gateway=192.168.1.1
-o parent=eth0
my_macvlan_network#创建一个使用 Macvlan 网络的容器
docker run --name my_macvlan_container --network my_macvlan_network nginx
7:自定义网络模式
除了上述内置的网络模式,你还可以使用 docker network create 命令创建自定义的 bridge 网络,以满足特定的网络需求,例如指定子网、网关、IP 范围等。
示例 1:使用如下命令创建一个自定义网络
docker network create
--subnet=172.21.0.0/16
--gateway=172.21.0.1
my_custom_network
参数说明:
- 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:为新创建的网络指定了一个名称,后续在创建容器时,可以通过这个名称将容器连接到该网络。
二:端口映射
(1)-P (大写):指的是容器应用 PORT 随机映射到宿主机器上的 PORT
自动绑定所有对外提供服务的容器端口,映射的端口将会从没有使用的端口池中自动随机选择,但是如果连续启动多个容器的话,则下一个容器的端口默认是当前容器占用端口号 + 1。
生产场景一般不使用随机映射,好处是由 docker 分配,宿主机器端口不会冲突。
(2)-p (小写):(宿主机器 PORT: 容器 PORT)
宿主机器 IP 不写表示 “0.0.0.0”,宿主机器 PORT 不写表示随机端口,容器 PORT 必须指定,可以同时对多个端口进行映射绑定。
指定端口映射,在标准化场景下使用频率高。
端口的取值范围 32768 -- 61000 之间
1:随机映射端口
在使用 docker run 命令创建并启动容器时,可以使用 -P(大写的 P)参数来实现随机端口映射。它会将容器中 EXPOSE 指令声明的所有端口随机映射到宿主机器的可用端口上。
假设你要运行一个 Nginx 容器,Nginx 默认监听 80 端口。使用以下命令启动容器:
#把容器内端口映射到应用程序上
docker run --rm -d -P nginx
docker ps
#测试容器IP:随机生成的映射端口
#暴露nginx端口
docker run --rm -d nginx
docker ps
2:指定映射端口
(1)固定端口
假设你要运行一个 Nginx 容器,并将容器的 80 端口映射到宿主机器的 8080 端口,可使用以下命令:
[root@localhost ~]# docker run --rm -d -p 8080:80 nginx
需要注意的是,在映射端口时,所使用的 docker 主机上的端口不能与其他容器或程序的端口冲突。否则,容器无法正常创建。
(2)宿主机随机端口
当使用小写的 -p 参数时,你可以不指定宿主机器的具体端口,只给出容器端口,Docker 会自动将容器端口映射到宿主机器的一个随机可用端口上。
[root@localhost ~]# docker run --rm -d -p 80 nginx
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89d94e902ea1 nginx "/docker-entrypoint…" 2 minutes ago Up 2 minutes 0.0.0.0:32769->80/tcp,:::32769->80/tcp amazing_banach
三:容器互联
容器互联,简单说就是让 多个 Docker 容器之间能互相通信、协同工作 的机制,核心是解决容器间 “怎么找到对方、怎么安全交互数据” 的问题
怎么实现 “互联”?(常见方式)
实际就是给容器规划 共享的网络环境 ,让它们能互相发现,常见方案有:
- 自定义网络(推荐):Docker 里创建一个 “虚拟网络”,然后启动容器时加入这个网络。容器间直接用 容器名 通信(比如
web
容器访问db
容器的 3306 端口),Docker 会自动解析名称 → 类似 “局域网里用主机名访问”。--link
选项(老旧方式,逐渐淘汰):启动容器时用--link 目标容器:别名
,让当前容器能通过 “别名” 访问目标容器。缺点:配置不灵活、不支持跨网络,新项目基本不用了。- Docker Compose / Swarm:编排工具里定义 “服务” 和 “网络”,启动后自动帮你把容器接入同一网络,直接用服务名互联(比如 Compose 里
services.web
访问services.db
)。- 宿主机端口映射(简单但不优雅):把容器端口映射到宿主机(比如
docker run -p 3306:3306
),其他容器通过 宿主机 IP + 端口 访问。缺点:依赖宿主机网络,多容器时管理麻烦,还可能暴露端口风险。
1:使用--link选项
#创建源容器
docker run -dit --name web01 centos:7
#创建接收容器
docker run -dit --name web02 --link web01:myweb01 centos:7
#测试容器互联
docker exec -it web02 /bin/bash
/ # cat /etc/hosts
/ # ping myweb01
四:容器间通信实现案例
1:常用选项及解释
(1) --driver, -d
该选项用于指定网络使用的驱动程序,默认值是 bridge。常见的驱动类型有:
- bridge:默认的网络驱动,适用于在单个 Docker 宿主机上创建的容器之间的通信。
- host:使用宿主机的网络栈,容器直接使用宿主机的网络接口,不进行网络隔离。
- overlay:用于在多个 Docker 宿主机之间创建跨主机的网络,通常用于 Docker Swarm 集群。
- macvlan:允许为容器分配一个 MAC 地址,使其在网络中看起来像一个独立的物理设备。
示例:创建一个使用 bridge 驱动的网络
docker network create -d bridge my_bridge_network
(2) --subnet
该选项用于指定网络的子网,格式为 CIDR 表示法(如 192.168.0.0/16 )。
示例:创建一个指定子网的网络:
docker network create --subnet=172.18.0.0/16 my_subnet_network
(3) --gateway
该选项用于指定网络的网关 IP 地址。
示例:创建一个指定子网和网关的网络
docker network create
--subnet=172.19.0.0/16
--gateway=172.19.0.1
my_gateway_network
(4) --ip-range
该选项用于指定容器可以使用的 IP 地址范围。
示例:创建一个指定子网、网关和 IP 范围的网络
docker network create
--subnet=172.20.0.0/16
--gateway=172.20.0.1
--ip-range=172.20.1.0/24
my_ip_range_network
(5) --internal
该选项用于将网络设置为内部网络,即容器无法访问外部网络。
示例:创建一个内部网络:
docker network create --internal my_internal_network
(6) --attachable
该选项可以允许独立的容器(非服务容器)连接到这个网络。
示例:创建一个可连接的网络:
docker network create --attachable my_attachable_network
2:容器间通信步骤
#创建自定义网络
docker network create my_net
#创建一个不在此自定义网络的容器
docker run -dit --name web03 centos:7
#创建两个容器,并加入自定义网络
docker run -dit --name pc01 --net=my_net centos:7
docker run -dit --name pc02 --net=my_net centos:7
#登陆到容器,测试通信结果
docker exec -it pc01 /bin/bash
/ # ping pc02 ##能通
/ # ping web03 ##不能通
第二节:数据持久化技术
一:Docker的数据管理
Docker 数据卷(Data Volumes)是 Docker 中用于持久化存储数据的一种机制,它在容器和宿主机之间建立了一种数据共享的方式,下面从多个方面详细解释 Docker 数据卷。
1:什么是数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过了容器的文件系统,直接将宿主机上的目录或文件挂载到容器内部。这意味着即使容器被删除,数据卷中的数据也不会丢失,从而实现了数据的持久化存储。
2:数据卷的作用
- 数据持久化:容器的生命周期可能是短暂的,当容器被删除时,其内部文件系统中的数据也会随之消失。而数据卷可以将数据存储在宿主机上,确保数据不会因为容器的删除而丢失。
- 数据共享:多个容器可以同时挂载同一个数据卷,从而实现容器之间的数据共享。这对于需要共享配置文件、日志文件或其他数据的应用场景非常有用。
- 数据备份和恢复:由于数据卷中的数据存储在宿主机上,因此可以方便地进行备份和恢复操作。
3:创建匿名数据卷
docker run -dit -v /data1 -v /data2 --name web04 centos:7
docker exec -it web04 /bin/bash
cd /data1
cd /data2
4:创建具名数据卷
(1)创建具名数据卷
docker volume create my_volume
(2)在创建容器时挂载具名数据卷
docker run -d -v my_volume:/data --name my_cotainer nginx
5:共享容器数据卷
如果希望在容器之间共享数据,可以使用下面的命令来实现。
docker run -dit --volumes-from web04 --name web05 centos:7 /bin/bash
这个命令的主要功能是基于 centos:7 镜像创建并启动一个名为 web05 的新容器,该容器会以交互模式、守护进程模式运行,并且会从 web04 容器中挂载所有的数据卷。
--volumes-from web04:这是一个关键参数,它的作用是让新创建的 web05 容器挂载 web04 容器中所有已经挂载的数据卷。这意味着 web05 容器可以访问和使用 web04 容器所使用的数据卷中的数据,实现数据的共享。
注意事项:
- 如果 web04 容器被删除,只要数据卷本身没有被删除,web05 容器仍然可以正常访问数据卷中的数据。
- 当多个容器共享同一个数据卷时,对数据卷中数据的修改会影响到所有挂载该数据卷的容器。
6:挂在主机目录作为数据卷
案例1:
#将宿主机上的 /data1 目录挂载到容器内的 /usr/local/apache2/htdocs 目录。
docker run -dit -p 8080:80 -v /data1:/usr/local/apache2/htdocs --name web06 httpd#创建测试文件
echo "ni hao">/data1/index.html#访问服务
curl 192.168.101.8080
案例2:
(1) 在宿主机创建挂载目录
mkdir -p /www/{conf,html}
(2) 准备数据
将编辑好的 nginx 配置文件拷贝到 /www/conf
将网站代码拷贝到 /www/html
(3) 创建容器
docker run -d -p 9090:80 \
-v /www/conf/nginx.conf:/etc/nginx/nginx.conf \-v /www/html:/www/html \
-v/www/nginx/log:/var/log/nginx \
--name web07 nginx /bin/bash -c "nginx"或docker run -d -p 9090:80 \
-v /www/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /www/html:/www/html \
-v/www/nginx/log:/var/log/nginx \
--name web08 nginx "nginx"
二:Docker数据管理注意事项
1:明确使用场景选择类型
- 匿名数据卷创建简单,但管理不便,适合临时存储中间数据。例如在构建过程中存储临时编译文件。
- 具名数据卷便于管理和共享,适用于需要持久化存储且后续会频繁使用的数据,如数据库数据。
- 挂载主机目录数据卷则方便与主机进行数据交互,适合需要与主机共享配置文件或数据的场景。
2:使用正确的路径
挂载主机目录作为数据卷时,必须使用绝对路径,否则会导致挂载失败。
3:数据卷清理
定期清理无用数据卷:使用 docker volume ls 查看所有数据卷,对于不再使用的匿名或具名数据卷,使用 docker volume rm 命令进行清理,避免占用过多磁盘空间。
4:容器内数据持久化
容器的文件系统是基于镜像层和容器层构建的。容器层的数据在容器删除时会丢失。因此,对于需要持久化的数据,应使用数据卷进行存储
多个容器可以挂载同一个数据卷来实现数据共享。但要注意并发访问问题,可能需要在应用层面实现数据同步机制,如使用锁机制或事务处理。
对于数据库、日志文件等关键数据,应将其存储在数据卷中,确保数据的持久化和可恢复性。例如,对于 MySQL 容器,将数据目录 /var/lib/mysql 挂载到数据卷上。