云计算百科
云计算领域专业知识百科平台

Docker 网络管理详解:本地网络模式与实战

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
  • 查看 IP:
    • Node1 容器 IP 应为 172.200.27.x
    • Node2 容器 IP 应为 172.200.21.x
  • 互相 Ping 测:
    进入 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 指令,原因如下:

  • 匿名卷陷阱:如果在 docker run 时没有指定 -v,Docker 会根据 Dockerfile 里的声明自动生成一个匿名卷(Anonymous Volume)。这个卷位于 /var/lib/docker/volumes/ 下的一长串哈希值目录中,难以管理和查找。
  • 数据残留:即使你删除了容器,匿名卷依然会残留在磁盘上占用空间,导致“删了容器但磁盘没释放”的假象。
  • 灵活性差:硬编码在镜像里的挂载点限制了容器的通用性。
  • 最佳实践:

    • Dockerfile:只负责安装环境和配置软件,尽量不声明 VOLUME(或者仅作为文档提示)。
    • 运行时:通过 docker run -v 宿主机路径:容器路径 显式指定挂载位置,确保数据完全可控
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Docker 网络管理详解:本地网络模式与实战
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!