Docker 网络管理详解:本地网络模式与实战
Docker 的网络功能是容器化部署的核心之一。理解 Docker 的默认网络模式,是构建复杂容器网络架构的基础。本文将详细介绍 Docker 的四种基础本地网络模式(Bridge、Host、Container、None),并通过实战命令演示它们的工作原理及适用场景。
一、Bridge 模式(桥接模式)
bridge 是 Docker 的默认网络模式。当 Docker 服务启动时,会在宿主机上创建一个名为 docker0 的虚拟网桥。
1. 工作原理
- NAT 上网:所有连接到 docker0 的容器都可以通过 NAT(网络地址转换)访问外网。
- 默认网段:容器默认获取 172.17.0.0/16 网段的 IP 地址。
- 局限性:由于每台 Docker Host 上的 docker0 网段完全一样,导致不同宿主机上的容器无法直接通过 IP 通信。
2. 查看默认网桥信息
在宿主机执行 ip a 可以看到 docker0 接口:
[root@]# ip a
...
6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:28:9c:5e:28 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
...
3. 查看 Docker 网络列表
[root@]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f2f19a5e2ebc bridge bridge local
5aeb2630e0f9 host host local
44b9cab07f8c none null local
4. 使用 Bridge 模式启动容器
如果不指定网络,默认即为 bridge 模式:
[root@]# docker run -it –network bridge centos:7.7.1908 /bin/bash
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum install net-tools -y
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 7312 bytes 64244058 (61.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5732 bytes 315893 (308.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
注意:容器内 IP (172.17.0.4) 与宿主机 docker0 (172.17.0.1) 在同一网段。
二、Host 模式(主机模式)
在 host 模式下,容器不会获得独立的 Network Namespace,而是与宿主机共用一个网络栈。
1. 特点
- 无隔离:容器直接使用宿主机的 IP 和端口。
- 高性能:没有 NAT 转发和网络虚拟化开销,网络性能最好。
- 端口冲突风险:多个容器如果绑定相同端口,会发生冲突。
2. 启动 Host 模式容器
[root@ ~]# docker run -it –network host centos:7 /bin/bash
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
[root@ /]# yum -y install iproute
[root@ /]# ip a
# 此时看到的网络配置与宿主机完全一致
#查看容器网络详情
docker network bridge
3. 端口冲突验证
如果在两个 host 模式的容器中都启动 httpd 服务(监听 80 端口):
yum -y install httpd
echo "test httpd" > /var/www/html/index.html
httpd -k start
httpd -t
容器 1:正常启动并访问。
容器 2:启动失败,报错如下:
(98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
结论:Host 模式下,容器间存在资源竞争,适用于对网络性能要求极高且不需要端口隔离的场景。
三、Container 模式(容器共享模式)
新创建的容器不会创建自己的网卡,而是与另一个指定的容器共享网络栈(IP、端口范围等)。
1. 特点
- 网络共享:两个容器可以通过 localhost 互相访问。
- 其他隔离:文件系统、进程列表等其他资源依然是隔离的。
- 应用场景:常用于 Sidecar 模式(如日志收集容器与应用容器共享网络)。
2. 实战演示
# 1. 启动第一个容器 c1
[root@ ~]# docker run -it –name c1 centos:7 /bin/bash
docker start c1
# 2. 启动第二个容器 c2,指定加入 c1 的网络
[root@ ~]# docker run -it –name c2 –network container:c1 centos:7 /bin/bash
此时,在 c2 中查看网络信息,其 IP 地址与 c1 完全相同。
四、None 模式(无网络模式)
1. 特点
- 仅回环:容器只有 lo (loopback) 网卡,没有任何外部网络连接。
- 高度安全:适用于不需要联网的批处理任务或高安全隔离场景。
2. 实战演示
[root@ ~]# docker run -it –network none centos:7.7.1908 /bin/bash
[root@0fd5a2fbc44c /]# yum -y install iproute
# 尝试安装软件会失败,因为没有网络
[root@0fd5a2fbc44c /]# ping baidu.com
ping: baidu.com: Name or service not known
3. 查看网络详情
通过 inspect 可以确认该容器没有分配 IP:
[root@ ~]# docker inspect 0fd5a2fbc44c
# 输出中 Networks 部分为空或仅包含 none 配置
💡 总结与建议
| Bridge | 高 | 中 (有 NAT) | 默认开发测试环境 |
| Host | 低 | 高 (无 NAT) | 高性能计算、监控代理 |
| Container | 中 | 高 | Sidecar 模式、K8s Pod 网络基础 |
| None | 最高 | N/A | 离线数据处理、安全隔离 |
在实际生产环境中,除了上述本地网络,通常还会配合自定义 Bridge 网络或 Overlay 网络(如 Docker Swarm/K8s)来解决跨主机通信问题。
📋 Flannel 跨主机容器通信部署指南
本指南基于 etcd + Flannel + Docker 架构,实现跨 Docker Host 的容器通信。
1. 环境准备 (Node1 & Node2)
在两台机器上均需执行以下操作:
-
关闭防火墙与 SELinux
systemctl stop firewalld
systemctl disable firewalld
setenforce 0 # 临时关闭
# 永久关闭需修改 /etc/selinux/config -
修改主机名
# Node1 执行
hostnamectl set-hostname node1# Node2 执行
hostnamectl set-hostname node2 -
配置 Hosts 解析
修改 /etc/hosts,确保两台机器能互相解析主机名及 etcd 地址。10.6.16.158 node1
10.6.16.158 etcd
10.6.16.159 node2
2. 软件安装
-
Node1 (作为 Etcd 服务器):
yum install -y etcd flannel
-
Node2 (作为客户端):
yum install -y flannel
3. Node1 配置 Etcd 服务
修改配置文件 /etc/etcd/etcd.conf:
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001"
启动服务:
systemctl start etcd
systemctl enable etcd
验证健康状态:
etcdctl -C http://etcd:4001 cluster-health
etcdctl -C http://etcd:2379 cluster-health
# 输出应包含 "cluster is healthy"
4. Node1 和 Node2 配置 Flannel 网络
修改配置 /etc/sysconfig/flanneld:
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"
在 Etcd 中写入网络配置:
etcdctl mk /atomic.io/network/config '{ "Network": "172.200.0.0/16" }'
etcdctl get /atomic.io/network/config
启动 Flannel:
systemctl start flanneld
systemctl enable flanneld
检查网卡:执行 ip a 应能看到 flannel0 网卡。
5. 配置 Docker 与 Flannel 结合 (Node1 & Node2)
Flannel 启动后会自动生成子网环境文件,需将其配置给 Docker。
查看子网环境 (两台机器分别查看,IP 会不同):
cat /run/flannel/subnet.env
# 示例输出: FLANNEL_SUBNET=172.200.27.1/24, FLANNEL_MTU=1472
修改 Docker 配置 /etc/docker/daemon.json:
-
Node1 示例 (根据实际 subnet.env 修改 bip):
{
"bip": "172.200.27.1/24",
"mtu": 1472,
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
} -
Node2 示例:
{
"bip": "172.200.21.1/24", // 注意这里 IP 会变
"mtu": 1472,
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
重启 Docker (两台机器都要做):
systemctl restart docker
验证 Docker 网桥:执行 ip a,docker0 的 IP 应与 subnet.env 中的 FLANNEL_SUBNET 一致。
6. 最终验证启动容器**:
- Node1: docker run -it –name test1 centos:7 /bin/bash
- Node2: docker run -itd –name test2 centos:7 /bin/bash
- Node1 容器 IP 应为 172.200.27.x
- Node2 容器 IP 应为 172.200.21.x
进入 Node1 的容器,Ping Node2 容器的 IP。如果通了,说明 Flannel 跨主机通信部署成功。
[!IMPORTANT]
如果还是ping不通,可以执行:
grep -ni ip_forward /etc/sysctl.conf
在重启Etcd和Flannel 就可以互通了
Docker 容器数据管理
📌 一、容器数据管理的三大痛点
01. 不便于修改
- 问题描述:当需要修改容器内文件(如 Nginx 的 HTML 页面),必须进入容器内部操作,若容器内无编辑器(如 vim),则需额外安装或复制文件,流程繁琐。
- 解决方案:通过挂载主机目录或数据卷,直接在宿主机上编辑文件,容器内自动同步。
02. 数据不可复用
- 问题描述:容器内修改的数据仅存在于当前容器生命周期中,删除容器后数据丢失;新创建的容器无法继承旧容器的数据。
- 解决方案:使用数据卷(Volume)或绑定挂载(Bind Mount),将数据存储在宿主机,多个容器可共享同一份数据。
03. 升级维护困难
- 问题描述:容器升级时需删除旧容器并创建新容器,若数据存储在容器内,所有配置、日志、数据库等都会随之丢失。
- 解决方案:将关键数据挂载到外部卷,升级容器时只需替换镜像,数据保持不变。
🧩 二、Docker 数据管理方式对比
| Volumes(数据卷) | Docker 管理的存储区域,位于 /var/lib/docker/volumes/ | 推荐用于生产环境 | 安全、隔离、可跨容器共享、支持备份迁移 |
| Bind mounts(绑定挂载) | 直接挂载宿主机任意目录到容器 | 开发调试、快速共享文件 | 灵活、直观,但权限控制较弱 |
| tmpfs | 数据存储在内存中,重启即消失 | 临时缓存、敏感数据 | 高性能、无磁盘 I/O,但不持久 |
🛠️ 三、数据卷实操命令详解
1. 创建并使用命名卷
# 创建名为 juan1 的卷
docker volume create juan1
# 启动容器并挂载该卷
docker run -it -v juan1:/data centos:7 /bin/bash
2. 匿名卷(无名称)
# 自动创建匿名卷,挂载到容器 /data 目录
docker run -it -v /data centos:7 /bin/bash
3. 绑定挂载(Bind Mount)
# 将主机 /test 目录挂载到容器 /data
docker run -it -v /test:/data centos:7 /bin/bash
4. 查看卷信息
# 列出所有卷
docker volume ls
# 查看某个卷的详细信息
docker volume inspect juan1
# 查看容器挂载信息
docker inspect <容器ID> | grep -A 10 "Mounts"
5. 多容器共享卷
# 容器 c1 挂载卷 juan2 到 /aaa
docker run -itd –name c1 -v juan2:/aaa centos:7.7.1908 /bin/bash
# 容器 c2 同样挂载 juan2 到 /bbb → 实现数据共享
docker run -itd –name c2 -v juan2:/bbb centos:7.7.1908 /bin/bash
# 容器 c3 继承 c1 的所有挂载点
docker run -itd –volumes-from c1 –name c3 centos:7.7.1908 /bin/bash
6. 只读挂载(防止误写)
# 容器内对 /ddd 目录只有读权限
docker run -it –name c4 -v /test/:/ddd:ro centos:7.7.1908 /bin/bash
7. 删除卷
# 删除指定卷
docker volume rm juan1
# 清理所有未使用的卷
docker volume prune
✅ 四、最佳实践建议
- 生产环境优先使用 Volumes:由 Docker 统一管理,安全性高,支持备份与迁移。
- 开发调试可用 Bind mounts:方便实时修改代码或配置文件。
- 避免在容器内写入重要数据:除非你明确知道容器会被持久化或使用卷。
- 定期清理无用卷:使用 docker volume prune 释放磁盘空间。
Docker 实战:制作 HTTPD 镜像与数据卷挂载应用
在 Docker 容器化部署 Web 服务时,数据持久化和内容更新是两个核心问题。如果将网页代码直接打包进镜像,每次修改页面都需要重新构建镜像,效率极低。
本文将演示如何制作一个自定义的 HTTPD 镜像,并通过 Bind Mount(绑定挂载) 的方式,实现宿主机目录与容器网页目录的实时同步,彻底解决“改代码难”的问题。
| FROM | 指定基础镜像,必须为第一条指令 | FROM centos:7.7.1908 |
| MAINTAINER | 维护者信息(推荐用 LABEL 替代) | LABEL maintainer=“admin@example.com” |
| RUN | 构建镜像时执行的命令 | RUN yum -y install httpd |
| COPY | 复制宿主机文件到镜像 | COPY index.html /var/www/html/ |
| ADD | 类似 COPY,支持自动解压压缩包 | ADD app.tar.gz /opt/ |
| EXPOSE | 声明容器暴露的端口 | EXPOSE 80 |
| CMD | 容器启动时执行的命令,可被 docker run 参数覆盖 | CMD [“nginx”, “-g”, “daemon off;”] |
| ENTRYPOINT | 容器启动时执行的命令,不会被覆盖 | ENTRYPOINT [“nginx”, “-g”, “daemon off;”] |
| VOLUME | 声明挂载点,运行时可挂载宿主机目录 | VOLUME [“/var/www/html”] |
🛠️ 环境准备与文件创建
首先,我们需要准备构建镜像所需的脚本文件和网页内容。
/test/ <– 在这里执行 docker build
├── Dockerfile (内容里写 ADD run-httpd.sh …)
├── run-httpd.sh (脚本文件必须在这里)
└── www/
└── index.html (网页文件)
创建工作目录
mkdir -p /test/www
cd /test
编写启动脚本 run-httpd.sh
Apache (httpd) 默认以后台模式运行,但在容器中前台进程必须保持运行,否则容器会立即退出。因此需要添加 -D FOREGROUND 参数。
vim run-httpd.sh
写入以下内容:
#!/bin/bash
/usr/sbin/httpd -D FOREGROUND
准备测试网页 index.html
cd /test/www
vim index.html
写入测试内容:
<h1>Test HTTPD Service via Volume!!!</h1>
📦 编写 Dockerfile 构建镜像
创建一个名为 Dockerfile 的文件,定义镜像的构建过程。
FROM centos:7
MAINTAINER "wenteacher@163.com"
# 【关键修改】先备份原源,再替换为可用的 vault 源
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup && \\
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo || \\
curl -o /etc/yum.repos.d/CentOS-Base.repo https://vault.centos.org/7.7.1908/os/x86_64/repodata/repomd.xml
# 清理缓存并安装 httpd
RUN yum clean all && \\
yum makecache fast && \\
yum -y install httpd
# 将启动脚本复制到容器内并赋予执行权限
ADD run-httpd.sh /run-httpd.sh
RUN chmod +x /run-httpd.sh
# 声明数据卷(注意:此处仅作声明,实际生产建议通过 -v 动态挂载)
VOLUME ["/var/www/html/"]
# 暴露 80 端口
EXPOSE 80
WORKDIR /
# 启动命令
CMD ["/bin/bash","/run-httpd.sh"]
构建镜像:
docker build -t centos-httpd:v1 .
🚀 容器运行与挂载实战
这是本教程的核心部分。我们将展示如何通过挂载宿主机目录来管理容器内的网页。
1. 基础测试(不挂载)
先验证镜像是否能正常启动服务。
docker run -d –name c2 centos-httpd:v1
# 获取容器 IP 进行测试
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' c2
curl http://<容器IP>
此时看到的是默认的 Apache 欢迎页或空页面,因为 /var/www/html 下还没有我们的 index.html。
2. 绑定挂载(Bind Mount)—— 推荐做法
通过将宿主机的 /test/www 目录挂载到容器的 /var/www/html,我们可以直接在宿主机修改代码,容器内实时生效。
# 停止并删除之前的测试容器
docker rm -f c2
# 启动新容器,使用 -v 挂载本地目录
docker run -d \\
–name web-server \\
-p 8080:80 \\
-v /test/www:/var/www/html \\
centos-httpd:v1
验证效果:
访问测试:在浏览器访问 http://宿主机IP:8080,应能看到 “Test HTTPD Service via Volume!!!”。
热更新测试:在宿主机修改文件,无需重启容器。
echo "Hello, updated content!" > /test/www/index.html
刷新浏览器,内容即刻改变。
⚠️ 避坑指南:关于 Dockerfile 中的 VOLUME 指令
在上面的 Dockerfile 中,我们写了 VOLUME ["/var/www/html/"]。但在实际企业级应用中,通常不建议在 Dockerfile 里写死 VOLUME 指令,原因如下:
最佳实践:
- Dockerfile:只负责安装环境和配置软件,尽量不声明 VOLUME(或者仅作为文档提示)。
- 运行时:通过 docker run -v 宿主机路径:容器路径 显式指定挂载位置,确保数据完全可控
网硕互联帮助中心






评论前必须登录!
注册