Docker数据持久化与网络架构

📑 目录

  • [一、Docker Volume(存储卷)](#一、Docker Volume(存储卷))
    • [1. 什么是存储卷及为什么需要](#1. 什么是存储卷及为什么需要)
    • [2. 存储卷分类](#2. 存储卷分类)
    • [3. 管理卷 Volume](#3. 管理卷 Volume)
    • [4. 绑定卷 bind mount](#4. 绑定卷 bind mount)
    • [5. 临时卷 tmpfs](#5. 临时卷 tmpfs)
    • [6. 总结:何时用哪种卷](#6. 总结:何时用哪种卷)
  • [二、Docker 网络架构](#二、Docker 网络架构)

一、Docker Volume(存储卷)

1. 什么是存储卷及为什么需要

  存储卷就是将宿主机本地文件系统的某个目录与容器内部某目录建立绑定关系。容器向该目录写数据时直接写入宿主机目录,绕过联合文件系统(UnionFS),以文件/目录形式存在于宿主机。Docker 存储的完整机制见 Docker 存储卷文档

生活案例:租了地下室并有钥匙。龙卷风(容器销毁)来了房子毁了,地下室(存储卷)依然安然无恙。

  为什么需要存储卷

问题 说明
数据丢失 容器文件系统本质是镜像层上的读写层,容器删除时读写层随之消失。有状态应用(MySQL/Kafka)需要持久化
性能问题 UnionFS 对修改删除效率低,如 Redis 持久化对 I/O 要求高
宿主机和容器互访不方便 需通过 docker cp,应用难以直接操作
容器间共享不方便 需要跨容器共享数据

2. 存储卷分类

类型 说明 宿主机位置
volume 管理卷 Docker 管理卷,daemon 自行创建目录,用户无需指定宿主机路径,耦合度低 默认 /var/lib/docker/volumes
bind mount 绑定卷 人工指定宿主机特定路径与容器特定路径建立关联 宿主机指定路径
tmpfs mount 临时卷 映射到宿主机内存中,容器停止即移除 内存

3. 管理卷 Volume

创建管理卷

  存储卷可以通过命令方式创建,也可以在创建容器的时候通过 -v and --mount指定。

方式一:Volume命令操作

  这里使用命令创建的管理卷,只是在宿主机创建卷存储目录,它本身不绑定任何容器内目录!!没有预先绑定关系。完整参数见 docker volume 命令

命令 功能
docker volume create 创建存储卷
docker volume inspect 显示存储卷详细信息
docker volume ls 列出存储卷
docker volume prune 清理所有无用数据卷
docker volume rm 删除卷(使用中的无法删除)

命令语法

bash 复制代码
# 创建卷(-d 指定驱动默认 local,--label 指定元数据)
docker volume create my-vol

# 查看详情(-f 指定格式如 json)
docker volume inspect my-vol

# 列出卷(--format 指定格式,-f 过滤,-q 仅名称)
docker volume ls

# 删除卷(-f 强制删除)
docker volume rm my-vol

# 清理无用卷(-f 不提示)
docker volume prune
方式二:-v或者--mount指定
bash 复制代码
# -v 方式:卷名:容器目录[:选项](ro 为 readonly)
docker run -d --name devtest -v myvol2:/app nginx:latest

# --mount 方式
docker run -d --name devtest --mount source=myvol2,target=/app nginx:latest

📌 --mount 的参数:type(bind/volume/tmpfs)、source/src(卷名)、destination/dst/target(容器路径)、ro/readonly(只读),类型不指定默认是volume。指定 ro 时宿主机可修改,容器内无法修改。

方式三:Dockerfile匿名卷

  通过Dockerfile的VOLUME可以创建docker管理卷。这个我们后续在Dockerfile 篇章中详细讲解

关键要点:

  • 宿主机目录为空时,volume 管理卷会把容器内文件自动拷贝到宿主机;bind mount 不会拷贝。
  • 修改文件,宿主机与容器之间数据同步
  • docker stop + docker rm 删除容器,卷内目录文件依然保留,删除容器不会丢失卷数据
  • 执行docker volume rm,卷本身才会被真正删除
  • 卷共享:多个容器挂载同一个卷即可实现容器间数据共享,修改一处全局同步生效

4. 绑定卷 bind mount

  -v 和-mount都可以完成绑定卷的创建 。

bash 复制代码
# -v 方式:宿主机目录:容器目录[:选项]
docker run -d -it --name devtest -v "$(pwd)"/target:/app nginx:latest

# --mount 方式
docker run -d -p 80:80 --name bind1 \
  --mount type=bind,source=/data/myworkdir/fs/webapp1,target=/usr/share/nginx/html \
  nginx:1.22.1

关键要点:

  • --mount 方式:宿主机目录不存在会启动报错(bind source path does not exist
  • -v 方式:宿主机目录不存在不会报错
  • 与 volume 最大不同:bind mount 模式下,容器挂载点目录本身存在的文件会消失(被宿主机空目录覆盖);volume 模式会拷贝容器内容到宿主机
  • 容器删除:不影响 bind 映射的宿主机文件
  • 共享:两个容器绑定同一宿主机目录即可

5. 临时卷 tmpfs

  临时卷数据位于内存中,在容器和宿主机之外。

局限性

  • 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
  • 这个功能只有在 Linux 上运行 Docker 时才可用。
bash 复制代码
# 方式一:--tmpfs
docker run -d -it --name tmptest --tmpfs /app nginx:1.22.1

# 方式二:--mount 指定参数
docker run -d -it --name tmptest --mount type=tmpfs,destination=/app nginx:latest

mount额外参数tmpfs-size(挂载大小字节,默认无限制)、tmpfs-mode(八进制文件模式,默认 1777)。

关键要点

  • tmpfs 会覆盖容器里面的文件。
  • 内容存在内存中,停止容器再启动内容完全消失。
  • 超出 tmpfs-size 会提示 No space left on device
  • 内容不存储在容器可写层(宿主机 find 找不到)。

总结:何时用哪种卷

类型 适用场景
volume Docker 宿主机文件系统一部分,用于不需要规划具体目录的场景
bind 完全依赖主机目录结构,用于目录需提前规划(如 MySQL 需大空间磁盘)
tmpfs 用于敏感文件存储,不想存到宿主机和容器可写层

扩展思考:Docker 存储卷默认是宿主机本地,无法调度到其他主机,跨主机可用 NFS/S3 等分布式存储解决;容器启动选项多易遗忘,复杂场景需容器编排工具(如 K8s)。


二、Docker 网络架构

Docker 网络的整体设计与配置详情见 Docker 网络文档

Docker 网络架构简介

  Docker 容器网络是为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作

系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口套接字、IP

路由表、防火墙等等与网络相关的模块。

  Docker 为实现容器网络,主要采用的架构由三部分组成:CNM、Libnetwork 和驱动。

CNM

  Docker 网络架构采用的设计规范是 CNM(Container Network Model)。 CNM 中规定

了 Docker 网络的基础组成要素:Sandbox、Endpoint、Network。

要素 说明
Sandbox(沙盒) 提供容器的虚拟网络栈(端口、套接字、IP 路由表、防火墙、DNS 配置),隔离容器网络与宿主机网络
Network(网络) Docker 内部的虚拟子网,使网络内参与者能通信
Endpoint(端点) 虚拟网络接口,负责创建连接。一个 Endpoint 只能接入某一个网络;容器接入多个网络需要多个 Endpoint
Libnetwork

  Libnetwork 是 CNM 的标准实现。Libnetwork 是开源库,采用 Go 语言编写(跨平台的),也是 Docker 所使用的库,Docker 网络架构的核心代码都在这个库中。Libnetwork 实现了 CNM 中定义的全部三个组件,此外它还实现了本地服务发现、基于 Ingress 的容器负载均衡,以及网络控制层和管理层等功能。

驱动

  驱动 主要负责实现数据层相关内容,例如网络的连通性和隔离性是由驱动来处理的。驱动通过实现特定网络类型的方式扩展了 Docker 网络栈,例如桥接网络和覆盖网络。

  Docker 内置了若干驱动,通常被称作原生驱动或者本地驱动。例如 Bridge Driver、Host Driver、Overlay Driver、MacVLan Driver、IPVLan Driver、None Driver 等等。每个驱动负责创建其上所有网络资源的创建和管理。

📌 Docker 安装时自动创建 docker0 网桥设备 (默认 172.17.0.1),用于容器与宿主机网络通信。

常见网络类型

网络类型 说明
bridge bridge 驱动会在 Docker 管理的主机上创建一个 Linux 网桥。默认情况下,网桥上的容器可以相互通信。也可以通过 bridge 驱动程序配置,实现对外部容器的访问。Docker 容器的默认网络驱动.当我们需要多个容器在同一个Docker主机上通信时,桥接网络是最佳选择。
host 对于独立容器,移除容器和Docker主机之间的网络隔离,并直接使用主机的网络。当网络堆栈不应该与Docker主机隔离,但是希望容器的其他资源被隔离时,主机网络是最佳选择。
container 这个模式指定新创建的容器和引进存在的一个容器共享一个网络 ,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的ip,而是和一个指定的容器共享ip,端口等,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信
none Docker 容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。容器完全网络隔离。
overlay 借助 Docker 集群模块 Docker Swarm 搭建的跨 Docker Daemon 网络。将多个Docker 守护进程连接在一起,使集群服务能够相互通信。当我们需要运行在不同Docker 主机上的容器进行通信时,或者当多个应用程序使用集群服务协同工作时,覆盖网络是最佳选择。

网络管理命令

完整参数见 docker network 命令

命令 功能
docker network create 创建网络
docker network connect 连接网络
docker network disconnect 断开网络
docker network ls 列出网络
docker network prune 删除不使用的网络
docker network inspect 查看网络详情
docker network rm 删除网络

命令语法

bash 复制代码
# 创建网络(-d 指定驱动,--gateway 网关,--subnet 子网,--ipv6:启用ipv6 )
docker network create --driver=bridge --subnet=192.168.0.0/16 br0

# 查看详情(-f 格式)
docker network inspect br0

# 将容器连接到网络。一旦连接,容器可以与同一网络中的其他容器通信。(--ip 指定 IP,--ip6:指定IPv6地址 )
docker network connect multi-host-network my_container1

# 断开网络(-f 强制)
docker network disconnect -f NETWORK CONTAINER

# 列出网络(-f 过滤,-q 仅 ID)
docker network ls

# 删除一个或多个网络(-f 强制)
docker network rm br0

# 清理无用网络(-f 不提示)
docker network prune

基本操作:

bash 复制代码
# 1. 创建网络并指定 IP 段
docker network create --subnet=172.18.0.0/16 mynetwork

# 2. 查看网络
docker network ls

# 3. 创建容器并加入网络
docker run -itd --name mynginx --network mynetwork nginx:1.22.1

# 4. 查看容器网络信息(看 Networks 节点,Gateway 172.18.0.1)
docker inspect mynginx

# 5. 不加入自定义网络的容器默认用 docker0 桥(Gateway 172.17.0.1)

# 6. 将运行中容器加入网络
docker network connect mynetwork mynginx2

# 7. 断开网络
docker network disconnect mynetwork mynginx2

# 8. 删除网络(网络被使用时无法删除,需先停止/删除所有连接容器)
docker network rm mynetwork

bridge 网络

  bridge 采用内置 bridge 驱动,底层使用 Linux 内核 Linux bridge 技术。使用软件网桥 docker0,允许连接同一网桥的容器通信,同时与未连接该网桥的容器隔离。默认创建的容器没有使用--network 参数指定要加入的 docker 网络时,都加入默认 bridge 网络 ,默认 bridge 与内核 docker0 网桥一一对应。

Docker Container 的 bridge桥接模式可以参考下图:

容器间网络通信:docker0 设备类比交换机/路由器,容器默认连接 docker0 通信。创建两个 busybox 容器集成了一百多个最常用 Linux 命令和工具(如 cat、echo、grep、mount、telnet 等)的精简工具箱(c1: 172.17.0.2, c2: 172.17.0.3),c1 可以 ping 通 c2 的 IP。

创建自定义 bridge

bash 复制代码
docker network create -d bridge new-bridge
# 创建时报错 Failed to Setup IP tables,可通过 systemctl restart docker 解决
# 自定义 bridge 子网默认 172.18.0.0/16

# 创建容器连接自定义 bridge
docker run -itd --name c3 --network new-bridge busybox

DNS 解析/容器名通信(重点):

网络 DNS 解析 通信方式
默认 bridge ❌ 不支持 DNS 只能用 IP 通信
自定义 bridge ✅ 支持 DNS 可直接用容器名通信

端口暴露和转发

bash 复制代码
# -P 随机端口映射(结果用 docker port 查看)
docker container run --name test-nginx --rm -d -P nginx

# -p 指定端口映射
docker container run --name test-nginx --rm -d -p 8088:80 nginx

📌 bridge 网络容器只能与同网络容器通信;对外提供服务需端口转发。

host 网络

  host 模式下容器不会获得独立的 Network Namespace,而是和宿主机共用同一个 Network Namespace,不虚拟自己的网卡/IP,直接使用宿主机 IP 和端口。通过 --network=host 指定。

bash 复制代码
# bridge 模式(独立网络)
docker container run --name c1 -itd busybox

# host 模式(共享宿主机网络)
docker container run --name c2 -itd --network=host busybox
# c2 的网络配置与宿主机完全一样(含 eth0、docker0、各 br- 网桥)

使用场景:bridge 通信需端口转发及 NAT 地址转换,消耗资源性能;host 最大好处是性能好,网络传输效率要求高时建议选 host。需考虑端口冲突,已被占用的端口不能再使用。

container 网络

  container 模式下,新容器使用其他容器的网络环境,不创建自己的网卡/IP,共享 IP、端口;文件系统、进程列表等仍隔离。两容器间不存在网络隔离,但与宿主机及其他容器存在网络隔离。

Docker Container 的 other container 网络模式实现逻辑:

  • 查找other container(即需要被共享网络环境的容器)的网络namespace

  • 将新创建的Docker Container(也是需要共享其他网络的容器)的namespace,使用other container 的 namespace

bash 复制代码
# 创建容器1
docker run -itd --name netcontainer1 busybox

# 创建容器2,共享容器1的网络
docker run -itd --name netcontainer2 --network container:netcontainer1 busybox
# 两个容器的 IP 和 mac 完全一样(共享同一网卡)

 停止容器1后,容器2 的 eth0 网卡消失只剩 lo;重启后网络恢复。

使用场景:可通过 localhost 访问 namespace 下的其他容器,传输效率高;但两容器存在依赖,依赖容器重启会导致另一服务网络不可用。

none 网络

  none 网络就是没有网络。挂在此网络下的容器除了 lo(本地回环)没有其他任何网卡。

bash 复制代码
docker container run -itd --name c3 --network none busybox
# 查看网络信息,发现只有 lo
docker container exec -it c3 ip a

使用场景:对安全性要求高且不需要联网的应用(如生成随机密码,避免被第三方获取);第三方应用需要 Docker 创建无网络容器,网络由第三方自己配置。


相关推荐
这个DBA有点耶1 小时前
同样48核配置TPS差1倍?高性价比数据库一体机的“软硬协同”才是分水岭
服务器·数据库·架构
嘟嘟嘟95271 小时前
Kubernetes 引入 KYAML:更安全的 YAML 子集
人工智能·架构·开源
myy-learn2 小时前
30-HTTP协议
网络·网络协议·http
ting94520002 小时前
Dograh 深度技术解析:开源自托管语音智能体平台架构、流水线与工程实践
人工智能·架构
开开心心就好2 小时前
免费刷题软件推荐,支持导入题库自动判题
网络·网络协议·tcp/ip·jupyter·智能手机·电脑·idea
行百里er4 小时前
HandlerInterceptor 和 WebFilter:两套 HTTP 请求拦截
后端·架构·监控
yanwumuxi4 小时前
Docker记录:误删宿主机挂载目录导致 PostgreSQL 数据丢失
docker·postgresql·容器
YUJIANYUE5 小时前
免费安卓手机版网络工具箱ping traceroute mtr等10+功能
网络
那年窗外下的雪.5 小时前
AIDC 学习日志|第 21 天|EVPN 多归属故障演练与中断窗口定位
网络·git·学习