Docker 网络完全指南

前尘往事:

Windows 下 Docker 安装与使用全攻略

Docker 真香定律:Windows 开发者如何用容器偷懒高效工作

Docker 进阶指南-Windows版:从镜像定制到容器编排,手把手带你玩转 Docker 实战


零、前言

如果你已经跟着前几篇文章跑起来了 Flask 应用和 Redis 容器,可能已经用到过 docker network create my-network 这样的命令。你是否有这样的疑问:

  • 为什么容器之间可以通过容器名互相访问?
  • 默认的 bridge 网络和自定义网络有什么区别?
  • 容器怎么访问宿主机的服务?
  • 多个宿主机上的容器能互相通信吗?

这篇指南将为你揭开 Docker 网络的神秘面纱,通过几个实战场景,逐步掌握 Docker 网络的使用。

一、Docker 网络模型简介

Docker 在安装时会创建三种默认网络,你可以用 docker network ls 查看:

powershell 复制代码
docker network ls

输出:

复制代码
NETWORK ID     NAME      DRIVER    SCOPE
e3f5e6f8b9a7   bridge    bridge    local
2b3c4d5e6f7g   host      host      local
7a8b9c0d1e2f   none      null      local
  • bridge :默认网络。每个容器启动时如果不指定网络,就会加入这个网络。容器之间可以通过 IP 通信,但不能通过容器名通信
  • host:容器直接使用宿主机的网络栈,没有网络隔离。
  • none:容器没有网络接口,完全隔离。

实际开发中,我们最常用的是自定义 bridge 网络。它比默认 bridge 功能更强,容器之间可以通过容器名互相发现,还能自定义 IP 地址范围。

二、Docker 网络驱动简介

Docker 支持多种网络驱动,最常用的有:

驱动 说明 适用场景
bridge 默认驱动,在单机上的容器间通信 单机开发、测试
host 容器共享宿主机网络栈 性能要求高,不想有额外网络开销的场景
overlay 跨多台 Docker 主机的容器通信 多机集群(Swarm 或 Kubernetes)
macvlan 为容器分配 MAC 地址,使其像物理设备一样接入网络 需要容器直接出现在物理网络中的场景
none 禁用网络 隔离容器

本篇文章重点讲解 bridgehost 驱动,以及如何创建和使用自定义 bridge 网络。

三、实战:创建自定义网络

我们从一个最简单的场景开始:两个容器需要在同一个网络中,通过容器名互相访问。

3.1 创建自定义网络

powershell 复制代码
docker network create my-net

查看创建的网络:

powershell 复制代码
docker network ls

3.2 运行两个容器并加入网络

powershell 复制代码
docker run -d --name redis-0331 --network my-net-0331 redis
docker run -d --name app-0331 --network my-net-0331 -p 5000:5000 flask-app-0331

注:flask-app-0331 是制作的镜像,可参考 Docker 真香定律:Windows 开发者如何用容器高效工作 这篇文章如何制作镜像。

现在,在 app-0331 容器内部,可以通过 redis-0331 这个主机名访问 Redis 容器。进入 app 容器测试:

powershell 复制代码
PS D:\> docker exec -it app-0331 bash
root@df63769307b6:/app# getent hosts redis-0331
172.20.0.2      redis-0331
root@df63769307b6:/app#

容器名解析成功。

3.3 检查网络详情

powershell 复制代码
docker network inspect my-net-0331

输出会显示这个网络下所有容器的名称、IP 地址等信息。你会看到容器名被自动解析为 IP。

json 复制代码
PS D:\> docker network inspect my-net-0331
[
    {
        "Name": "my-net-0331",
        "Id": "218584c3e80f6942c8c6321e96445bf56de2558cc539f22afbaccfa8ab3d8b62",
        "Created": "2026-03-31T12:24:38.165057052Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv4": true,
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",
                    "Gateway": "172.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Options": {
            "com.docker.network.enable_ipv4": "true",
            "com.docker.network.enable_ipv6": "false"
        },
        "Labels": {},
        "Containers": {
            "3a65f9dddb9a00beb57510e4d69b419eaef670017f1aa09599385b9b04497ec7": {
                "Name": "redis-0331",
                "EndpointID": "8f47cc159861daeb59d685fb1a21afcae77c98e06b7d723726ac9bbcb5d56b6b",
                "MacAddress": "3a:23:84:e0:75:89",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            },
            "df63769307b65d20e79e234cd8c850cfe7dd7d60c7c94200a6d207c66f5a829d": {
                "Name": "app-0331",
                "EndpointID": "bc62eb76e80b6becaed2ced109153a9b6e66a3daff5b50e4237c3f949fa1830c",
                "MacAddress": "fe:37:13:6b:65:75",
                "IPv4Address": "172.20.0.3/16",
                "IPv6Address": ""
            }
        },
        "Status": {
            "IPAM": {
                "Subnets": {
                    "172.20.0.0/16": {
                        "IPsInUse": 5,
                        "DynamicIPsAvailable": 65531
                    }
                }
            }
        }
    }
]

3.4 优势总结

  • 使用自定义网络后,容器之间可以通过容器名直接通信,无需知道 IP。
  • 网络内的容器可以互相访问,但外部无法直接访问(除非通过端口映射 -p)。
  • 网络可以被多个容器共享,并且支持动态添加/移除容器。

四、网络连接与断开

有时你需要让一个已经运行的容器加入某个网络,或者从网络中移除。

4.1 将容器连接到已有网络

powershell 复制代码
docker network connect my-net-0331 my-container

4.2 断开连接

powershell 复制代码
docker network disconnect my-net my-container

4.3 实战:把 Redis 容器连接到两个网络

假设你已经有一个 Redis 容器运行在 my-net 中,现在需要它也能被另一个网络 other-net 中的容器访问:

powershell 复制代码
docker network create other-net
docker network connect other-net redis

现在 redis 容器同时属于两个网络,两个网络内的容器都可以通过 redis 这个名字访问它。这在微服务架构中很常见。

五、容器如何访问宿主机服务?

有时候容器需要访问宿主机上运行的服务(比如一个本地的 MySQL 数据库,没有容器化)。默认情况下,容器内的 localhost 指的是容器自身,不是宿主机。

解决方案:

  • Linux 上,使用 host.docker.internal 这个特殊域名。
  • Windows / macOS 上,Docker Desktop 也支持 host.docker.internal

例如,如果你的宿主机上运行着 MySQL 并监听 3306 端口,在容器内可以这样连接:

python 复制代码
import mysql.connector
conn = mysql.connector.connect(
    host="host.docker.internal",
    port=3306,
    user="root",
    password="secret"
)

注意 :在 Linux 上,如果使用 --network host 模式,容器可以直接使用 localhost 访问宿主机,但会失去网络隔离。通常推荐使用 host.docker.internal

六、端口映射深入理解

我们经常用 -p 8080:80 把容器的 80 端口映射到宿主机的 8080。这个映射其实是在 宿主机网络命名空间容器网络命名空间 之间建立了一个转发规则。

6.1 原理

  • 当外部访问宿主机的 8080 端口时,请求被转发到容器的 80 端口。
  • 容器内部不需要做任何特殊配置,它仍然认为自己在监听 80 端口。
  • 一个容器可以映射多个端口:-p 8080:80 -p 8443:443

6.2 查看端口映射

powershell 复制代码
docker port 容器名

输出类似:

复制代码
80/tcp -> 0.0.0.0:8080
powershell 复制代码
PS D:\> docker port app-0331
5000/tcp -> 0.0.0.0:5000
5000/tcp -> [::]:5000

6.3 绑定到特定 IP

默认端口映射会监听宿主机的所有 IP 地址。如果只想让本机访问,可以绑定到 127.0.0.1

powershell 复制代码
docker run -p 127.0.0.1:8080:80 ...

这样只有本机可以访问,局域网其他机器无法访问。

七、host 网络模式

如果你希望容器与宿主机共享网络栈(没有网络隔离),可以使用 --network host

powershell 复制代码
docker run --network host nginx

此时容器内的 localhost 就是宿主机的 localhost,容器不需要 -p 映射端口,因为它的网络直接就是宿主机的网络。

适用场景

  • 性能要求极高,不想经过 Docker 的网络虚拟化。
  • 需要监听大量端口,不想一个一个映射。
  • 容器需要访问宿主机的某些服务,且 host.docker.internal 无法使用(比如某些 Linux 环境)。

缺点

  • 容器之间网络隔离消失,容易冲突。
  • 容器与宿主机共享端口空间,如果宿主机上某个端口被占用,容器也无法启动。

八、none 网络模式

完全禁用网络。容器只能通过 --network none 启动,这样的容器没有网络接口,无法对外通信。

powershell 复制代码
docker run --network none busybox ip addr

只看到 lo 回环接口。

适用场景:极度安全的场景,容器不需要任何网络访问,比如只做离线计算的容器。

九、跨主机通信简介

单机 Docker 的网络很简单,但生产环境往往需要多台机器上的容器互相通信。这需要用到 overlay 网络驱动。

9.1 Overlay 网络基础

  • 需要 Docker SwarmKubernetes 等编排工具。
  • 通过 VXLAN 等隧道技术,让不同主机上的容器感觉像在同一个二层网络中。
  • 容器之间可以通过服务名互相发现(内置 DNS)。

9.2 简单示例(使用 Docker Swarm)

powershell 复制代码
# 初始化 Swarm
docker swarm init

# 创建 overlay 网络
docker network create -d overlay my-overlay

# 在不同节点上部署服务,服务会加入该网络
docker service create --name web --network my-overlay --replicas 3 nginx

Swarm 会自动处理服务发现和负载均衡。对于普通开发者,了解 overlay 的存在即可,深入使用通常结合生产环境。

十、常见网络问题与排查

10.1 容器无法访问外网

检查 Docker 守护进程是否配置了 DNS。默认容器使用宿主机的 DNS 配置。如果宿主机 DNS 有问题,可以启动容器时指定:

powershell 复制代码
docker run --dns 8.8.8.8 ...

10.2 端口映射不生效

  • 确认宿主机防火墙是否允许该端口。
  • 确认没有其他程序占用该端口(可以用 netstat -ano | findstr :8080 查看)。
  • 检查容器是否确实在监听正确的端口(docker logs 查看日志)。

10.3 容器之间 ping 不通

  • 确认两个容器在同一个自定义网络中(不是默认 bridge)。
  • 尝试用 IP 而不是容器名测试,排除 DNS 问题。
  • 检查容器内是否有防火墙规则(通常没有)。

10.4 如何修改已运行容器的网络?

不能直接修改,需要先停止、删除,然后重新创建时指定网络。但可以通过 docker network connect 将容器加入额外网络(前提是容器启动时已经有一个网络)。

10.5 删除网络失败

如果网络正在被容器使用,无法删除。需要先断开所有容器:

powershell 复制代码
docker network disconnect 网络名 容器名
docker network rm 网络名

十一、小结

  1. 始终使用自定义网络,而不是默认 bridge。这样容器名解析、网络隔离、动态连接都更灵活。
  2. 合理规划网络:不同项目使用不同的网络,避免服务发现混乱。
  3. 开发时使用 --network host 要谨慎,容易忽略环境差异。
  4. 端口映射尽量绑定到 127.0.0.1,除非需要对外暴露。
  5. 定期清理无用网络docker network prune 会删除所有未使用的网络。

别忘了点赞、收藏、转发 哦!

相关推荐
风向决定发型丶2 小时前
K8S CPU绑核详解
云原生·容器·kubernetes
风曦Kisaki3 小时前
# Linux 磁盘查看命令详解:df 与 du
linux·运维·网络
斯普信云原生组3 小时前
Docker 开源软件应急处理方案及操作手册——镜像管理与构建故障
docker·容器·eureka
攻城狮在此3 小时前
华为交换机Console口密码如何清除
运维·网络·华为
hhcgchpspk5 小时前
网速上传下载流量监测工具尝试
网络·python·cmd·psutil
亚空间仓鼠5 小时前
OpenEuler系统常用服务(四)
linux·运维·服务器·网络
刘佬GEO6 小时前
【无标题】
网络·人工智能·搜索引擎·ai·语言模型
中议视控6 小时前
展厅和会议网络可编程中央控制系统主机支持HomeKit技术和BACnet网络
网络
MichealChen0105086 小时前
Influxdb-cluster使用docker部署
运维·docker·容器