Docker 高级管理--容器通信技术与数据持久化
Docker 高级管理–容器通信技术与数据持久化
Docker 容器通讯技术
一、Docker 容器网络基础
Docker 容器是一种轻量级的虚拟化技术,其网络隔离基于 Linux 的网络命名空间(Network Namespace)实现。每个容器在创建时会被分配一个独立的网络命名空间,这使得容器拥有专属的网络资源,具体包括:
-
独立 IP 地址:容器会从所在网络的地址池获取一个 IP,用于在网络中标识自己。
-
端口空间:容器内的端口与宿主机及其他容器的端口相互独立,避免了端口冲突问题。
-
路由表:容器可以有自己的路由规则,决定网络数据包的转发路径。
-
网络接口:容器会有虚拟的网络接口,用于连接到网络。
容器网络的核心目标是打破这种隔离,实现多方面的通讯需求:
-
容器与容器之间能够进行数据传输,例如微服务架构中不同服务容器的交互。
-
容器与宿主机之间可以交换信息,比如容器向宿主机的日志服务发送日志。
-
容器能够接入外部网络,访问互联网上的资源,如从外部仓库拉取依赖包。
Docker 的网络驱动是实现这些通讯的关键,不同的网络驱动采用不同的技术实现,适用于多样化的应用场景,为容器通讯提供了灵活且高效的解决方案。
二、容器通讯关键技术
(一)bridge 网络
bridge 网络是 Docker 默认的网络驱动,在 Docker 安装完成后,会自动创建一个名为 docker0 的虚拟网桥,其工作机制较为复杂,具体流程如下:
- 网络创建:
-
当创建一个新的 bridge 网络(可以是默认的 docker0,也可以是自定义的 bridge 网络)时,Docker 会在宿主机上创建一个虚拟网桥设备。
-
同时,为该网桥分配一个子网,例如默认 docker0 的子网可能为 172.17.0.0/16。
-
可通过docker network create --driver bridge --subnet 192.168.10.0/24 my-bridge创建指定子网的自定义 bridge 网络。
- 容器连接:
-
当容器连接到 bridge 网络时,Docker 会为容器创建一对虚拟以太网接口(veth pair)。
-
其中一个接口被放置在容器的网络命名空间中,命名为 eth0,并为其从网桥的子网中分配一个 IP 地址,如 172.17.0.2。
-
另一个接口则被放置在宿主机的网络命名空间中,以 vethxxx 的形式命名,并连接到虚拟网桥上。
-
可使用docker run --network=my-bridge --ip=192.168.10.10 -d --name=test-container nginx指定容器连接的网络及 IP。
- 容器间通讯:
-
以容器 A(IP:172.17.0.2)向容器 B(IP:172.17.0.3)发送数据为例:
-
容器 A 的应用程序生成数据包,目标 IP 为 172.17.0.3,通过容器内的 eth0 接口发送。
-
数据包通过 veth pair 传输到宿主机的 vethxxx 接口,进而到达虚拟网桥。
-
虚拟网桥接收到数据包后,查看目标 IP 地址,发现是同一网桥下的容器 B,便将数据包转发到容器 B 对应的 veth 接口,最终到达容器 B 的 eth0 接口。
-
可通过在容器内使用ping 172.17.0.3测试容器间连通性。
- 与宿主机通讯:
-
容器与宿主机通讯通过网络地址转换(NAT)实现。
-
当容器访问宿主机时,若目标是宿主机的物理网卡 IP,数据包会从容器的 eth0 出发,经 veth pair 到网桥,再由网桥转发到宿主机的物理网卡对应的网络接口。
-
反之,宿主机访问容器时,会通过 NAT 将宿主机的地址转换为容器的 IP 地址,再进行数据包传输。
-
例如宿主机 IP 为 192.168.1.10,容器 IP 为 172.17.0.2,在宿主机上使用curl 172.17.0.2可访问容器内服务。
- 访问外部网络:
-
容器访问外部网络时,数据包从容器出发,经 veth pair 到网桥,然后由宿主机的 iptables 规则进行源地址转换(SNAT),将容器的 IP 地址转换为宿主机的公网 IP 地址,再通过宿主机的物理网卡发送到外部网络。
-
外部网络返回的数据包则通过相反的路径,经宿主机的目的地址转换(DNAT)后到达容器。
-
在容器内使用ping www.baidu.com可测试访问外部网络情况。
使用场景:
-
适用于同一宿主机上的容器通讯。
-
在开发和测试环境中,可方便地创建多个独立的 bridge 网络,实现不同组容器之间的隔离,配置简单,适合快速搭建测试环境。
(二)host 网络
当容器使用 host 网络模式时,容器会直接复用宿主机的网络命名空间,意味着容器与宿主机共享所有的网络资源,其工作细节如下:
- 网络共享:
-
容器没有自己独立的 IP 地址、端口空间和路由表,完全使用宿主机的网络配置。
-
例如,宿主机的 IP 地址为 192.168.1.100,那么容器对外展示的 IP 地址也是 192.168.1.100。
-
使用docker run --network=host -d --name=host-network-container nginx创建使用 host 网络的容器。
- 端口使用:
-
容器内应用程序使用的端口直接占用宿主机的端口,不需要进行端口映射。
-
如果容器内的应用程序监听 80 端口,那么宿主机的 80 端口就会被占用,其他程序(包括其他容器)无法再使用该端口。
-
若宿主机 80 端口已被占用,再启动使用 host 网络且监听 80 端口的容器会失败,需先释放端口。
- 性能优势:
-
由于省去了虚拟网桥的转发以及 NAT 转换的过程,数据包可以直接在应用程序和网络之间传输,减少了网络延迟和性能损耗,网络性能接近原生网络。
-
可通过iperf工具测试容器网络性能,对比 host 网络与其他网络模式的差异。
使用场景:
-
适用于对网络性能要求较高的场景。
-
一些需要绑定到宿主机特定端口且不需要网络隔离的应用,例如某些监控代理程序,需要监听宿主机的特定端口来收集数据。
-
注意:使用 host 网络会使容器失去网络隔离性,容器内的网络行为可能会影响到宿主机和其他容器,在生产环境中需谨慎使用。
(三)overlay 网络
overlay 网络是实现跨宿主机容器通讯的重要方式,其技术实现较为复杂,涉及多个组件和步骤:
- 网络创建前提:
-
需要一个键值存储系统(如 Consul、Etcd、ZooKeeper)来保存网络的配置信息,包括网络拓扑、IP 地址分配等。
-
参与 overlay 网络的所有宿主机都需要能够访问该键值存储系统。
-
以 Consul 为例,可通过docker run -d -p 8500:8500 --name=consul consul启动 Consul 服务,然后在各宿主机上配置–cluster-store=consul://consul-ip:8500和–cluster-advertise=host-ip:2376。
- 网络初始化:
-
当创建一个 overlay 网络时,Docker 会在键值存储系统中注册该网络的信息,包括网络 ID、子网、网关等。
-
每个加入该网络的宿主机都会从键值存储系统中获取网络配置,并在本地创建相关的网络设备。
-
使用docker network create -d overlay --subnet=10.0.0.0/24 my-overlay创建 overlay 网络。
- 隧道建立:
-
宿主机之间会建立一个虚拟隧道,常用的隧道技术有 VXLAN。
-
VXLAN 会将容器的网络数据包封装在 UDP 数据包中,并使用宿主机的 IP 地址作为外层地址进行传输。
-
每个 overlay 网络会有一个唯一的 VXLAN 网络标识符(VNI),用于区分不同的 overlay 网络。
-
可通过ip link show查看宿主机上的 VXLAN 设备,如 vxlan-xxx。
- 容器接入:
-
当容器连接到 overlay 网络时,Docker 会为容器分配一个来自 overlay 网络子网的 IP 地址,并创建一对 veth 接口。
-
一端连接到容器的网络命名空间,另一端连接到宿主机上的虚拟网桥(如 br0),该虚拟网桥与 VXLAN 隧道相关联。
-
在不同宿主机上使用docker run -d --name=overlay-container1 --network=my-overlay nginx和docker run -d --name=overlay-container2 --network=my-overlay nginx创建接入 overlay 网络的容器。
- 跨主机通讯流程:
-
以容器 A(位于宿主机 1)与容器 B(位于宿主机 2)通讯为例:
-
容器 A 生成目标 IP 为容器 B 的数据包,通过 veth 接口发送到宿主机 1 的虚拟网桥。
-
宿主机 1 的网络协议栈识别到目标 IP 属于 overlay 网络,将数据包封装到 VXLAN 数据包中,外层源 IP 为宿主机 1 的 IP,外层目标 IP 为宿主机 2 的 IP。
-
封装后的数据包通过宿主机 1 的物理网卡发送到宿主机 2。
-
宿主机 2 接收到数据包后,进行 VXLAN 解封装,得到原始的容器数据包,然后根据目标 IP 将数据包转发到容器 B 对应的 veth 接口,最终到达容器 B。
-
可在容器 A 中使用ping 容器B的overlay网络IP测试跨主机通讯。
使用场景:
- 在分布式应用中,当应用的不同组件分布在多个宿主机上时,overlay 网络能让这些组件像在同一局域网内一样通讯,非常适合微服务架构,例如电商平台的订单服务容器和支付服务容器分别在不同宿主机上,通过 overlay 网络实现实时的数据交互。
(四)macvlan 网络
macvlan 网络让容器能够像物理设备一样在网络中存在,其工作原理如下:
- 物理网卡虚拟化:
-
macvlan 网络会将宿主机的物理网卡(如 eth0)虚拟出多个子接口,这些子接口被称为 macvlan 接口。
-
每个 macvlan 接口都有一个唯一的 MAC 地址。
-
可通过docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 my-macvlan创建 macvlan 网络,其中 parent 指定物理网卡。
- 容器网络配置:
-
当容器连接到 macvlan 网络时,Docker 会为容器分配一个 macvlan 接口,并将其添加到容器的网络命名空间中。
-
同时,为该接口分配一个 IP 地址(可以手动指定或从地址池获取),该 IP 地址与宿主机所在的物理网络在同一网段。
-
使用docker run -d --name=macvlan-container --network=my-macvlan --ip=192.168.1.100 nginx创建容器并指定 IP。
- 通讯方式:
-
容器通过 macvlan 接口直接与物理网络中的设备进行通讯,不需要经过宿主机的网桥或 NAT 转换。
-
容器发送的数据包会直接从 macvlan 接口发送到物理网卡,再传输到网络中;接收的数据包则从物理网卡直接传递到 macvlan 接口,再进入容器。
-
物理网络中的其他设备可直接通过ping 192.168.1.100与容器通讯。
使用场景:
-
需要与传统网络设备(如交换机、路由器)进行通讯的场景,例如一些工业控制领域的容器化应用,需要与现场的 PLC(可编程逻辑控制器)通过特定的网络协议通讯,而 PLC 通常只识别物理网络中的设备。
-
当需要对容器进行网络流量监控和管理时,由于 macvlan 网络中的容器在物理网络中具有独立身份,可以使用传统的网络监控工具(如 Wireshark)直接对其流量进行捕获和分析,在宿主机上使用wireshark -i eth0并过滤容器 IP 即可。
(五)none 网络
none 网络为容器提供了一个完全封闭的网络环境,其配置和特点如下:
- 网络接口情况:
-
容器在 none 网络中没有任何网络接口,包括回环接口(lo)。
-
这意味着容器内部无法进行任何网络通讯,即使是容器内的进程之间通过网络协议通讯也无法实现。
-
使用docker run --network=none -d --name=none-network-container nginx创建使用 none 网络的容器,进入容器后使用ip addr可发现没有网络接口。
- 适用场景实例:
-
一些进行大量本地数据处理的任务,如视频渲染、数据分析等,这些任务不需要与外部进行网络交互,使用 none 网络可以提高容器的安全性,避免网络攻击。
-
用于测试容器的网络隔离性,验证在完全没有网络的情况下容器的运行状态,例如测试应用在无网络环境下的错误处理机制。
三、跨主机容器通讯方案
(一)Flannel
Flannel 是 CoreOS 推出的轻量级跨主机容器网络解决方案,其工作原理和特点如下:
- 网络规划:
-
Flannel 使用键值存储系统(如 Etcd)来管理网络配置,会为每个宿主机分配一个独立的子网,例如宿主机 1 分配 10.244.1.0/24,宿主机 2 分配 10.244.2.0/24 等。
-
这些子网的信息会存储在键值存储系统中。
-
首先在 Etcd 中设置网络配置,etcdctl set /coreos.com/network/config ‘{“Network”:“10.244.0.0/16”,“Backend”:{“Type”:“vxlan”}}’。
- 虚拟网卡创建:
-
每个宿主机上会创建一个名为 flannel0 的虚拟网卡,该网卡是一个 TUN 设备(隧道设备),用于在用户空间和内核空间之间传递网络数据包。
-
启动 Flannel 后,通过ip addr show flannel0可查看该网卡信息。
- 路由配置:
-
Flannel 会根据键值存储系统中的子网信息,在每个宿主机上配置路由规则。
-
例如,宿主机 1 会添加一条路由规则,将目标为宿主机 2 子网(10.244.2.0/24)的数据包转发到 flannel0 虚拟网卡。
-
使用route -n可查看宿主机上的路由规则,会有指向其他宿主机子网的路由条目。
- 后端实现:
-
VXLAN 后端:与 overlay 网络的 VXLAN 实现类似,将容器数据包封装在 UDP 数据包中进行传输,通过宿主机的 IP 地址进行路由。可在 Flannel 配置中指定"Type":"vxlan"启用。
-
host-gw 后端:直接将宿主机作为网关,当需要向其他子网的容器发送数据包时,直接将数据包发送到目标子网所在的宿主机,由该宿主机负责转发到容器。这种方式没有隧道封装开销,性能更好,但要求宿主机之间必须在同一个二层网络中,配置时指定"Type":“host-gw”。
- 通讯流程:
-
以容器 A(位于宿主机 1,IP:10.244.1.2)向容器 B(位于宿主机 2,IP:10.244.2.2)发送数据包为例:
-
数据包从容器 A 发送到宿主机 1 的虚拟网桥(如 docker0)。
-
宿主机 1 根据路由规则,将数据包转发到 flannel0 虚拟网卡。
-
如果使用 VXLAN 后端,flannel0 会对数据包进行封装,发送到宿主机 2;如果使用 host-gw 后端,数据包会直接发送到宿主机 2。
-
宿主机 2 接收到数据包后,根据路由规则转发到对应的容器 B。
-
可在容器 A 中使用ping 10.244.2.2测试跨主机通讯。
(二)Calico
Calico 是一种高性能的容器网络方案,基于 BGP 协议实现,其工作机制如下:
- 网络架构:
- Calico 由多个组件构成,包括 Felix(运行在每个宿主机上的代理程序)、BGP Speaker(负责路由信息交换)、Etcd(存储网络配置和路由信息)等。
四,示例
1.Bridge模式
(1)创建一个叫my-net的bridge类型的网络
语法
docker netwrok create -d bridge my-net
# 使用docker network create命令创建一个自定义网络
# -d bridge:指定网络驱动类型为bridge(桥接网络),这是Docker中最常用的网络模式之一
# my-net:为创建的网络指定名称,便于后续容器连接时引用
# 执行成功后,返回的字符串(如8cbb0ca05ac2d...)是该网络的唯一标识符(NETWORK ID)
docker network create -d bridge my-net
8cbb0ca05ac2d333ec7d2075c8a701b5c530ffda6601954576c3482984a2db9b
(2)查看都有哪些网络
# 执行docker network ls命令,用于列出当前Docker主机上所有的网络
[root@localhost ~]# docker network ls
# 输出结果的表头说明:
# NETWORK ID:网络的唯一标识符,由一串随机字符组成
# NAME:网络的名称,用于区分不同的网络
# DRIVER:创建网络时使用的驱动类型,决定了网络的工作模式
# SCOPE:网络的作用范围,local表示仅在当前宿主机有效
NETWORK ID NAME DRIVER SCOPE
bbcaf1076e02 bridge bridge local # Docker默认的bridge网络,未指定网络时容器默认连接到此
197afed09677 host host local # host网络,使用此网络的容器共享宿主机网络栈
8cbb0ca05ac2 my-net bridge local # 之前通过docker network create -d bridge my-net创建的自定义bridge网络
7a24b8f13131 none null local # none网络,使用此网络的容器无任何网络接口,完全隔离
(3) 运行一个容器并连接到新建的my-net网络
语法
docker run -dit --rm --name busybox1 --net=my-net busybox sh -c 'while true;do echo hello;done'
# 使用docker run命令创建并启动容器
docker run -dit # 组合参数:# -d:后台运行容器(守护进程模式)# -i:保持标准输入打开(允许容器接收外部输入)# -t:分配伪终端(提供交互式shell)--rm # 容器停止后自动删除容器文件(避免残留无用容器)--name busybox1 # 指定容器名称为busybox1,便于后续管理--net=my-net # 指定容器连接到名为my-net的网络(等同于--network=my-net)busybox # 使用busybox镜像(轻量级Linux工具集,适合快速测试)sh -c 'while true;do echo hello;done' # 容器启动后执行的命令:# 启动shell(sh)并执行-c后的脚本# 脚本内容:无限循环打印"hello"
(4)运行一个容器并加入到my-net网络
语法
docker -dit --rm --name busybox2 --net=my-net busybox sh
# 1. 启动一个基于busybox镜像的容器,命名为busybox2,连接到my-net网络
# -itd参数组合:-i(交互式) -t(分配终端) -d(后台运行)
# --rm:容器退出后自动删除
# sh:容器启动后执行shell,但不指定具体命令,shell会等待用户输入
docker run -itd --rm --name busybox2 --net=my-net busybox sh
1033dd5280988a2bb57ebf738fd1d118ffd64495e14e9dc33919b64799c378ea # 容器ID# 2. 使用docker exec命令进入已运行的容器(使用容器ID的前四位简写)
# -it:保持交互式终端
# sh:在容器内执行shell命令,进入容器的命令行环境
docker exec -it 1033 sh
/ # # 容器内的命令提示符,表示已成功进入容器# 3. 在busybox2容器内执行ping命令,测试与busybox1容器的网络连通性
# busybox1:目标容器名称,Docker网络会自动解析容器名称到对应的IP
# 172.18.0.2:busybox1的实际IP地址(从my-net网络分配)
ping busybox1
PING busybox1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.133 ms # 成功接收到响应,延迟0.133毫秒
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.496 ms # 第二个响应,延迟0.496毫秒
2.Host模式
(1)创建一个host网络模式的容器
语法
docker run -dit --name dufu --net=host busybox
# 使用docker run命令创建并启动容器
docker run -tid # 组合参数:# -t:分配伪终端(模拟一个终端环境)# -i:保持标准输入打开(允许容器接收外部输入)# -d:后台运行容器(守护进程模式)--net=host # 指定容器使用宿主机的网络命名空间# 容器将直接使用宿主机的IP地址和端口,不创建独立网络栈--name dufu # 为容器指定名称为dufu,便于后续管理和操作busybox # 使用busybox镜像(轻量级Linux工具集,适合快速测试)# 容器启动后默认执行/bin/sh(未指定其他命令时)
(2)进入该host模式的容器
语法
docker exec -it dufu sh
# 1. 使用docker exec命令进入已运行的容器(名称为dufu)
# -it:保持交互式终端,允许用户输入命令
# sh:在容器内启动shell,进入容器的命令行环境
docker exec -it dufu sh
/ # # 容器内的命令提示符,表示已成功进入容器# 2. 在容器内执行ifconfig命令,查看网络接口配置
# 注意:此命令在使用--net=host参数的容器中应显示宿主机的网络接口
ifconfig# 3. 输出的网络接口信息解析
# 注意:此处显示的是一个名为br-06e3e11bf0bb的网桥接口,这与预期的host模式不符
br-06e3e11bf0bb Link encap:Ethernet HWaddr 02:42:74:0D:77:80 inet addr:172.18.0.1 Bcast:172.18.255.255 Mask:255.255.0.0 # IPv4地址及广播地址、子网掩码inet6 addr: fe80::42:74ff:fe0d:7780/64 Scope:Link # IPv6链路本地地址UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 # 接口状态(UP表示激活)和最大传输单元RX packets:7 errors:0 dropped:0 overruns:0 frame:0 # 接收数据包统计TX packets:15 errors:0 dropped:0 overruns:0 carrier:0 # 发送数据包统计collisions:0 txqueuelen:0 # 冲突计数和发送队列长度RX bytes:300 (300.0 B) TX bytes:1622 (1.5 KiB) # 接收和发送的总字节数
3.Container模式
先创建一个host1容器
[root@localhost ~]# docker run -tid --name host1 busybox
再创建一个host2容器共享host1容器的网络
语法
docker run -dit --name host2 --net=container:host1 busybox
# 使用docker run命令创建并启动容器
docker run -dit # 组合参数:# -d:后台运行容器(守护进程模式)# -i:保持标准输入打开(允许容器接收外部输入)# -t:分配伪终端(模拟一个终端环境)--name host2 # 为容器指定名称为host2--net=container:host1 # 指定网络模式为"container",即与另一个容器共享网络命名空间# 此处表示host2将与已存在的host1容器共享网络配置busybox # 使用busybox镜像(轻量级Linux工具集)# 未指定命令时,默认执行/bin/sh(启动一个shell)
查询host1容器的网络
语法
docker exec -it host1 ifconfig
[root@localhost ~]# docker exec -it host1 ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:14 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:1156 (1.1 KiB) TX bytes:0 (0.0 B)lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
同样的语法查看host2
[root@localhost ~]# docker exec -it host2 ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:14 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:1156 (1.1 KiB) TX bytes:0 (0.0 B)lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
4.None模式
创建一个名none1的none模式的容器
语法
docker run -itd --net=none --name none1 busybox sh
# 创建并启动一个新的 Docker 容器
docker run \-itd \ # -i: 保持标准输入打开,允许交互;-t: 分配伪终端;-d: 后台运行容器--net=none \ # 设置容器的网络模式为 none,即完全隔离网络,没有网络接口--name none01 \ # 指定容器的名称为 none01busybox \ # 使用 busybox 镜像(轻量级 Linux 工具集)sh # 容器启动后执行的命令,这里是启动一个 shell
# 使用 docker exec 命令在已运行的容器中执行新命令
# -i: 保持标准输入打开,允许交互
# -t: 分配伪终端,提供类似登录 shell 的体验
# none01: 目标容器的名称
# sh: 要在容器内执行的命令(启动 shell)
[root@localhost ~]# docker exec -it none01 sh# 容器 shell 提示符,表示已成功进入容器内部
/ # # 在容器内部执行 ifconfig 命令查看网络接口配置
# 由于容器使用 --net=none 模式,仅存在本地回环接口(lo)
/ # ifconfig# 本地回环接口(Loopback)配置信息
lo Link encap:Local Loopback # IPv4 地址配置(仅容器内部可见)inet addr:127.0.0.1 Mask:255.0.0.0# IPv6 地址配置inet6 addr: ::1/128 Scope:Host# 接口状态:已启用(UP)、支持回环(LOOPBACK)、正在运行(RUNNING)UP LOOPBACK RUNNING MTU:65536 Metric:1# 接收/发送数据包统计(当前均为 0,因为尚未使用)RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
5.Overlay模式
创建 overlay 网络
docker network create \--driver overlay \--subnet 10.0.9.0/24 \my-overlay-network
# 初始化 Swarm 集群
docker swarm init --advertise-addr <MANAGER-IP># 创建全局 overlay 网络
docker network create \--driver overlay \--attachable \my-swarm-network
部署服务到 overlay 网络
docker service create \--name my-web \--network my-overlay-network \--replicas 3 \nginx:alpine
6.macvlan模式
创建 macvlan 网络(桥接模式)
docker network create -d macvlan \--subnet=192.168.1.0/24 \--gateway=192.168.1.1 \-o parent=eth0 \my-macvlan-net
创建带 VLAN 标签的 macvlan 网络
docker network create -d macvlan \--subnet=192.168.2.0/24 \--gateway=192.168.2.1 \-o parent=eth0.10 \ # VLAN 10 的子接口my-vlan10-net
启动使用 macvlan 的容器
docker run -itd --network=my-macvlan-net \--name my-container \alpine:latest
7.自定义网络模式
1. 自定义桥接网络(Bridge)
-
特点:单主机内的容器通信,支持 IP 地址管理和容器间自动发现。
-
适用场景:单机环境下的微服务通信。
-
示例
# 创建自定义桥接网络 docker network create \--driver bridge \--subnet 172.18.0.0/16 \--gateway 172.18.0.1 \my-bridge-net
2. Overlay 网络
-
特点:跨主机通信,支持 Docker Swarm 集群。
-
适用场景:分布式系统、多节点集群。
-
示例
# 创建跨主机 overlay 网络(需先初始化 Swarm) docker swarm init docker network create \--driver overlay \--attachable \my-overlay-net
3. Macvlan 网络
-
特点:容器直接连接物理网络,每个容器有独立 MAC 地址。
-
适用场景:传统应用迁移、需要直接 IP 访问的场景。
-
示例
# 创建 macvlan 网络 docker network create \-d macvlan \--subnet=192.168.1.0/24 \--gateway=192.168.1.1 \-o parent=eth0 \my-macvlan-net
自定义网络 vs 默认网络
特性 | 默认桥接网络(docker0) | 自定义桥接网络 |
---|---|---|
容器间通信方式 | 需 IP 地址或 --link 参数 | 可通过容器名直接通信 |
隔离性 | 所有容器共享同一网络 | 不同网络间完全隔离 |
IP 地址管理 | 自动分配,难以自定义 | 可指定 Subnet、网关等 |
DNS 服务 | 仅支持 localhost | 内置 DNS,支持服务发现 |
安全性 | 较低(容器间可随意通信) | 较高(默认拒绝外部访问) |
使用自定义网络的优势
-
简化服务间通信:同一网络内的容器可通过名称互相访问,无需手动配置 IP。
# 启动两个容器并连接到自定义网络 docker run -d --name web --network my-bridge-net nginx docker run -it --network my-bridge-net alpine ping web # 可直接使用容器名
-
提高安全性:不同网络间的容器默认无法通信,需通过显式配置(如端口映射或防火墙规则)。
-
精细的 IP 管理:为特定应用分配专用 IP 段,避免地址冲突。
-
支持高级网络功能:
- 基于
overlay
实现跨主机集群。 - 通过
macvlan
集成传统网络。 - 结合第三方驱动实现网络策略(如 Calico 的网络 ACL)。
- 基于
管理自定义网络
# 列出所有网络
docker network ls# 查看网络详情
docker network inspect my-bridge-net# 删除网络
docker network rm my-bridge-net# 连接容器到已存在的网络
docker network connect my-bridge-net existing-container# 从网络断开容器
docker network disconnect my-bridge-net existing-container
五,端口映射
Docker 的 ** 端口映射(Port Mapping)** 是一种将容器内部端口暴露到宿主机外部的机制,允许外部网络通过宿主机的 IP 地址和端口访问容器内的服务。这是容器与外部世界通信的主要方式,尤其适用于需要从宿主机或其他网络设备访问容器服务的场景。
核心概念
- 容器端口:容器内部服务监听的端口(如 Web 服务器监听
80
端口)。 - 宿主机端口:宿主机上用于转发请求到容器的端口。
- 映射关系:通过
宿主机端口:容器端口
的格式定义映射(如8080:80
表示将宿主机的8080
端口映射到容器的80
端口)。
为什么需要端口映射?
默认情况下,容器的网络是隔离的,外部无法直接访问容器内的服务。端口映射通过在宿主机上创建一个代理,将外部请求转发到容器内部,从而实现:
- 服务暴露:让外部用户或其他系统可以访问容器内的应用。
- 端口冲突解决:多个容器可共享宿主机的不同端口,避免端口冲突。
- 安全控制:通过选择暴露的端口,精细控制容器的访问权限。
如何配置端口映射?
1. 使用 docker run
命令
在创建容器时,使用 -p
或 --publish
选项指定映射关系:
# 格式:-p 宿主机端口:容器端口
docker run -d -p 8080:80 nginx # 将宿主机的 8080 端口映射到容器的 80 端口# 映射多个端口
docker run -d -p 8080:80 -p 4433:443 nginx # 同时映射 HTTP 和 HTTPS 端口# 随机映射宿主机端口(由 Docker 自动分配)
docker run -d -P nginx # 使用大写 P,宿主机端口会随机分配
2. 使用 Docker Compose
在 docker-compose.yml
中配置 ports
字段:
version: '3'
services:web:image: nginxports:- "8080:80" # 宿主机:容器
3. 查看端口映射信息
# 查看容器详细信息(包含端口映射)
docker inspect container_name_or_id | grep Ports# 简化查看端口映射
docker port container_name_or_id
端口映射模式
1. 特定 IP 绑定
将端口映射限制在特定的宿主机 IP 上:
# 只在宿主机的 127.0.0.1 上监听 8080 端口
docker run -d -p 127.0.0.1:8080:80 nginx
2. UDP 端口映射
默认映射的是 TCP 端口,如需映射 UDP 端口,需显式指定:
docker run -d -p 53:53/udp dnsmasq # 映射 UDP 53 端口
3. 动态端口分配
使用 -P
(大写)让 Docker 自动分配宿主机端口:
docker run -d -P nginx # 例如:宿主机随机分配 32768-61000 范围内的端口
端口映射与网络模式
网络模式 | 端口映射支持 | 说明 |
---|---|---|
bridge | 支持(默认模式) | 容器有独立 IP,通过宿主机端口转发访问。 |
host | 不支持(无需映射) | 容器直接使用宿主机网络,端口与宿主机共享(如容器监听 80 ,宿主机 80 直接被占用)。 |
none | 不支持 | 容器无网络连接,无法进行端口映射。 |
overlay | 支持(需结合 Swarm 服务) | 用于跨主机集群,通过 ingress 网络实现端口暴露。 |
macvlan | 支持(需网络设备配合) | 容器直接获取物理网络 IP,可直接通过该 IP 访问,无需端口映射。 |
常见场景示例
1. Web 服务器暴露
# 将宿主机 80 端口映射到 Nginx 容器的 80 端口
docker run -d -p 80:80 nginx
2. 数据库访问
# 将宿主机 3306 端口映射到 MySQL 容器的 3306 端口
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password mysql
3. 开发环境调试
# 将宿主机 3000 端口映射到 Node.js 应用容器的 3000 端口
docker run -d -p 3000:3000 node-app
注意事项
- 端口冲突:确保宿主机上的目标端口未被其他服务占用。
- 安全风险:暴露不必要的端口可能引入安全漏洞,建议仅映射必要的端口。
- 性能影响:端口映射会引入少量网络开销,但通常可忽略不计。
- 防火墙配置:若宿主机有防火墙(如
iptables
、firewalld
),需确保允许外部访问映射的端口。
总结
端口映射是 Docker 网络的核心功能之一,它通过将容器端口与宿主机端口绑定,实现了容器服务的外部可访问性。合理使用端口映射,结合不同的网络模式,可以构建安全、高效的容器化应用架构。
数据持久化技术
Docker 数据持久化是一种机制,用于确保容器产生的数据在容器停止、重启或删除后不会丢失。由于容器的生命周期通常是短暂的,默认情况下容器内的数据会随容器删除而丢失,因此需要专门的持久化方案来保存关键数据(如数据库文件、配置文件、日志等)。
为什么需要数据持久化?
- 容器重建不丢数据:容器因更新、故障恢复等原因被删除重建后,历史数据能保留(如数据库中的用户记录)。
- 数据共享:多个容器之间需要共享数据(如分布式应用的缓存数据)。
- 性能优化:将 I/O 密集型操作(如数据库写入)放在高性能存储上。
- 分离关注点:将应用逻辑与数据存储解耦,符合容器化最佳实践。
Docker 数据持久化的主要方式
Docker 提供了三种主要的数据持久化机制:
1. 数据卷(Volumes)
- 特点:由 Docker 管理的主机文件系统中的目录,完全独立于容器生命周期。
- 优点:易于管理、可备份、支持共享和迁移。
- 适用场景:数据库存储、配置文件、共享存储。
示例:
# 创建命名卷
docker volume create my-data# 挂载卷到容器(读写模式)
docker run -d -v my-data:/app/data nginx# 匿名卷(自动创建,但难以追踪)
docker run -d -v /app/logs nginx # 未指定卷名,Docker 自动生成随机名称
2. 绑定挂载(Bind Mounts)
- 特点:将主机上的任意目录或文件直接挂载到容器中。
- 优点:灵活,可直接访问主机文件。
- 缺点:依赖主机文件系统结构,移植性差。
- 适用场景:开发环境(如挂载源代码)、配置文件注入。
示例:
# 挂载主机当前目录到容器的 /app(读写模式)
docker run -d -v $(pwd):/app node# 指定绝对路径
docker run -d -v /host/path:/container/path nginx
3. tmpfs 挂载
- 特点:临时挂载在内存中,数据不会写入磁盘。
- 优点:高性能、安全(数据不会持久化)。
- 缺点:重启丢失、容量受限(受主机内存限制)。
- 适用场景:临时存储敏感数据(如密钥、会话缓存)。
示例:
# 挂载 tmpfs 到容器的 /run 目录(默认大小为 64MB)
docker run -d --tmpfs /run nginx# 指定 tmpfs 大小
docker run -d --tmpfs /run:size=100m nginx
数据卷 vs 绑定挂载
特性 | 数据卷(Volumes) | 绑定挂载(Bind Mounts) |
---|---|---|
存储位置 | Docker 管理目录(通常在 /var/lib/docker/volumes ) | 主机任意路径 |
创建方式 | 自动创建或 docker volume create | 手动指定主机路径 |
权限控制 | 更好的隔离性(Docker 管理) | 依赖主机文件系统权限 |
移植性 | 高(不依赖主机路径) | 低(依赖特定主机路径) |
适用场景 | 持久化数据(如数据库) | 开发环境、配置注入 |
高级用法
1. Docker Compose 中的数据卷
version: '3'
services:db:image: mysqlvolumes:- mysql-data:/var/lib/mysql # 命名卷- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 绑定挂载volumes:mysql-data: # 声明命名卷
2. 数据卷备份与恢复
# 备份数据卷
docker run --rm -v my-data:/data -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /data# 恢复数据卷
docker run --rm -v my-data:/data -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar --strip 1
3. 只读挂载
# 以只读方式挂载配置文件
docker run -d -v /host/config:/container/config:ro nginx
生产环境最佳实践
- 分离数据与应用:将数据库、日志等数据存储在独立卷中,避免与容器耦合。
- 定期备份:对重要数据卷进行定期备份(如使用
crontab
结合tar
命令)。 - 监控存储:监控数据卷的使用情况,避免磁盘空间占满导致应用故障。
- 使用外部存储:在 Kubernetes 等编排系统中,优先使用云提供商的持久卷(如 AWS EBS、GCE PD)。
- 避免敏感数据硬编码:通过环境变量或 secret 管理工具注入敏感数据,而非存储在容器或卷中。
总结
数据持久化是容器化应用的关键需求,Docker 通过数据卷、绑定挂载和 tmpfs 提供了灵活的解决方案。在实际应用中,需根据数据类型、访问模式和生命周期选择合适的持久化方式,并结合备份策略确保数据安全。