Docker网络配置入门与排障:bridge、host、自定义网络 📅 发布时间:2026/9/18 18:30:19 👁 浏览次数: 刚玩 Docker 的时候我总觉得 Docker 网络配置是最玄学的部分容器里能访问外网宿主机却访问不到映射端口两个容器明明跑在同一台机器上互相 ping 却像隔了座山。后来把 bridge、host、none、自定义网络、Docker Compose 网络这几块逐个拆开才发现它本质上就是 Linux 网络命名空间、虚拟网桥、iptables 转发和 DNS 解析的组合拳。这篇小白笔记不打算堆概念而是按我平时排障的顺序把 Docker 网络配置的常用操作、参数选择、坑点排查一次讲透。你如果刚学会 docker run或者被容器互联、端口映射、跨主机通信折腾过下面这些内容可以直接拿去对照操作。1. 先看透 Docker 网络配置的底层逻辑1.1 容器网络不是“虚拟网卡”这么简单很多人第一次看 Docker 网络会以为容器就是多了一张虚拟网卡配个 IP 就能通。这个理解只对了一半。容器确实有自己的网络命名空间里面有独立的网卡、路由表、iptables 规则和端口空间但真正让它和外界发生关系的是 Docker 在宿主机上创建的一堆虚拟设备。默认情况下Docker 会创建一个名叫 docker0 的虚拟网桥类似一台看不见的交换机。你每启动一个使用默认 bridge 网络的容器Docker 就创建一对 veth pair一头插在容器里看起来像 eth0另一头插在 docker0 上。容器发出的包先到 docker0再根据宿主机路由和 NAT 规则决定是转到外网、转到宿主机还是转到另一个容器。这也是为什么容器里看到的 IP 通常是 172.17.0.x而宿主机上多出一个 docker0 接口。这个 172.17.0.0/16 不是公网地址也不会自动被外部网络访问。外部想访问容器要么走端口映射要么让宿主机做路由转发要么使用 macvlan、ipvlan 这类更接近物理网络的方案。理解了这个模型很多问题就顺了容器访问外网靠 SNAT外部访问容器靠 DNAT容器之间通信靠同一网桥或同一自定义网络二层转发跨主机通信则要靠 overlay 或底层网络打通。我自己排障时有个习惯先问三个问题容器有没有 IP容器能不能 ping 通网关宿主机有没有对应的 NAT 规则。这三个问题能覆盖大部分“网络不通”的场景。不要一上来就重启 Docker先看清楚数据包从哪来、到哪去比盲目改配置有效得多。1.2 五个常用网络驱动bridge、host、none、overlay、macvlanDocker 网络驱动不少但日常真正高频的就五个bridge、host、none、overlay、macvlan。bridge 是默认驱动适合绝大多数单机容器场景。它给容器分配独立 IP通过端口映射暴露服务容器之间可以走 IP 或自定义网络里的 DNS 名称。host 直接复用宿主机网络命名空间容器不分配独立 IP端口也直接占用宿主机端口。它的好处是性能损耗小、网络路径短坏处是端口冲突明显隔离性差。none 则是给容器一个只有 lo 的网络命名空间适合完全不需要网络的批处理任务或者你自己想手动配网络的高级场景。overlay 主要用在多主机通信通常和 Swarm 模式配合。它把多个 Docker 宿主机的网络打通让不同主机上的容器像在同一个二层网络里。macvlan 和 ipvlan 更特殊它们让容器直接出现在物理网络里容器能从公司路由器或交换机拿到真实网段 IP。这样做的好处是容器像物理机一样被外部访问不需要端口映射坏处是配置复杂对交换机、网卡混杂模式、宿主机通信都有要求。小白阶段先掌握 bridge 和自定义 bridge再学 host、none最后碰 overlay、macvlan这个顺序最省心。驱动典型用途容器 IP端口映射隔离性小白建议bridge单机默认场景有需要较好必须掌握host高性能、少一层 NAT无独立 IP不需要差按需使用none无网络批处理只有 lo不需要最强了解即可overlay多主机 Swarm有需要较好进阶再学macvlan容器像物理机入网物理网段 IP不需要中等谨慎使用1.3 端口映射、容器 IP、DNS 三者的关系端口映射解决的是“外面怎么进来”。容器 IP 解决的是“容器在 Docker 网络里是谁”。DNS 解决的是“容器之间怎么互相找到”。这三件事经常被混在一起。比如你跑了一个 MySQL 容器容器内监听 3306你在宿主机用-p 3307:3306映射。此时宿主机访问127.0.0.1:3307能到 MySQL但容器里仍然认为自己在 3306 上。另一个容器要连它如果两者在同一自定义网络里应该写mysql:3306而不是127.0.0.1:3307。因为 127.0.0.1 在容器内部指向容器自己不是宿主机也不是别的容器。默认 bridge 网络里容器之间可以通过 IP 互访但容器名不会自动解析。很多人用--link让容器名可解析但--link已经过时不建议在新项目里使用。正确做法是创建自定义 bridge 网络然后把容器接进去。用户自定义网络里 Docker 会内置一个 DNS 服务容器名、服务名、别名都能解析。这个差异是新手最容易踩的坑同样两个容器默认 bridge 里 ping 容器名失败自定义网络里就能成功。端口映射也不是越多越好。默认-p 8080:80会监听宿主机所有网卡的 8080相当于把服务暴露到局域网甚至公网具体取决于宿主机防火墙和网络位置。如果你只想本机访问可以写-p 127.0.0.1:8080:80。这个细节在开发机上无所谓在服务器上就是安全边界。我见过有人把数据库端口直接-p 3306:3306暴露出去然后被扫描、被爆破最后还以为是 Docker 网络有问题。网络配置不只是“能不能通”还包括“该不该通”。2. 默认网络实操bridge、host、none 怎么用、怎么选2.1 查看 Docker 网络现状的命令清单上手之前先学会看。Docker 网络相关命令不多但每一个都很关键。docker network ls列出当前网络默认会看到 bridge、host、none 三个。docker network inspect bridge能看到这个网络的子网、网关、已连接容器。docker network inspect 容器名不行要 inspect 网络名或 ID。想看容器用了哪个网络可以用docker inspect 容器名重点看 NetworkSettings.Networks 部分。想知道端口映射结果用docker port 容器名。这些命令看起来简单但排障时能省很多时间。# 查看所有网络 docker network ls # 查看 bridge 网络详情 docker network inspect bridge # 查看容器网络信息 docker inspect my-container --format {{json .NetworkSettings.Networks}} # 查看端口映射 docker port my-container # 查看容器内 IP 和路由 docker exec -it my-container ip addr docker exec -it my-container ip route我习惯在容器里再装一点基础工具比如iproute2、curl、ping。很多精简镜像里没有这些命令排障时非常难受。你可以在构建镜像时加进去也可以临时用docker exec进容器后安装。注意生产镜像不要为了排障塞太多工具可以单独跑一个 debug 容器接入同一网络。这个技巧很实用docker run --rm -it --network mynet nicolaka/netshoot里面工具齐全能直接测 DNS、抓包、路由。2.2 默认 bridge 网络能通但不够聪明默认 bridge 网络是 Docker 安装后自动创建的。你运行docker run -d nginx如果不指定--network容器就接入这个网络。它会拿到 172.17.0.0/16 里的一个 IP网关通常是 172.17.0.1也就是宿主机上的 docker0。容器访问外网时包从 docker0 出来经过宿主机 iptables 的 MASQUERADE 规则做源地址转换然后走宿主机物理网卡出去。外部访问容器时必须通过-p映射Docker 会写 DNAT 规则把宿主机端口的流量转到容器 IP 和端口。默认 bridge 的缺点也很明显。第一容器之间只能通过 IP 互访容器名不解析。第二所有容器都在同一个大网段里没有网络隔离。第三默认 bridge 的 DNS 和宿主机/etc/resolv.conf绑定较紧某些环境下容器内 DNS 解析会出问题。第四默认 bridge 不支持服务发现容器重启后 IP 可能变化写死 IP 很容易失效。所以默认 bridge 适合临时跑一两个容器不适合多服务项目。我早期做实验时经常把 MySQL、Redis、Web 都跑在默认 bridge 里然后用 IP 互连。结果一重启IP 变了配置全挂。后来改成自定义网络容器名直接当主机名用配置文件再也不用改 IP。这个转变很小但项目可维护性提升很大。你可以把默认 bridge 理解成“临时停车场”能停但不适合长期停放和精细管理。2.3 host 与 none极端场景下的取舍host 网络让容器直接使用宿主机网络命名空间。启动方式很简单docker run --network host nginx。此时 nginx 监听的是宿主机的 80 端口不需要-p。它的优点是网络路径短没有 NAT 转换性能通常比 bridge 好一点。对于高并发反向代理、监控采集、需要拿到真实客户端 IP 的服务host 网络有时更合适。但它的代价是端口隔离消失。如果宿主机 80 已经被占用容器就起不来多个容器也不能同时用 host 网络监听同一个端口。在 Linux 上 host 网络很直接。在 Docker Desktop for Windows 和 macOS 上host 网络的行为曾经和 Linux 不一样因为 Docker Desktop 跑在虚拟机里。新版本 Docker Desktop 对 host 网络的支持在变化具体要看你用的版本和设置。如果你在 Windows 上装了 Docker Desktop发现--network host后 localhost 访问行为不符合预期不要怀疑命令先确认 Docker Desktop 的版本和网络实现。虚拟机网络配置和 Docker Desktop 的网络转发是两层宿主机端口、WSL2、虚拟机网卡任何一层没通都会导致访问失败。none 网络则相反它给容器一个完全隔离的网络命名空间只有 lo。适合不需要网络的场景比如只做本地文件处理、密钥生成、离线计算。你可以手动在容器里配网卡但这属于高级操作。小白阶段记住一句话需要网络就用 bridge 或自定义 bridge需要极致网络性能再考虑 host完全不需要网络才用 none。不要为了“看起来高级”乱选驱动。2.4 自定义 bridge 网络小白最该掌握的方案自定义 bridge 网络是我最推荐新手优先掌握的内容。创建命令不复杂docker network create \ --driver bridge \ --subnet 172.20.0.0/16 \ --gateway 172.20.0.1 \ mynet然后启动容器时指定--network mynet。这样做有几个好处。第一容器之间可以通过容器名解析。第二网络隔离清晰不同项目可以放不同网络互不干扰。第三可以自定义子网避开公司内网或虚拟机网段冲突。第四后续接 Docker Compose、微服务项目时思路完全一致。你可以把自定义 bridge 理解成“自己拉的交换机”比默认 docker0 更可控。选择子网时有个经验不要随手用 172.17.0.0/16因为它和默认 bridge 冲突。也不要和公司办公网、虚拟机 NAT 网段重叠比如很多虚拟机软件默认用 192.168.56.0/24、192.168.100.0/24。你可以用ip route或route print看宿主机现有路由再选一个不冲突的网段。如果已经冲突Docker 可能起不来或者容器访问宿主机和外部网络时走错路由。修改默认地址池可以在/etc/docker/daemon.json里配置default-address-pools改完重启 Docker。这个操作会影响所有新网络生产环境改之前先记录原配置。{ default-address-pools: [ { base: 10.201.0.0/16, size: 24 } ] }改完执行systemctl restart docker。注意正在运行的容器可能会中断已有网络不会自动重建。更稳妥的做法是给单个网络显式指定--subnet先小范围验证再考虑全局默认池。这个细节在 Ubuntu 网络配置、CentOS 7 网络配置、麒麟服务器操作系统网络配置里都类似核心是别让 Docker 网段和宿主机网段打架。3. 容器互联与 DNS为什么容器名有时能 ping 通有时不行3.1 用户自定义网络的内置 DNS 解析容器名能不能解析取决于它接入了什么网络。默认 bridge 网络没有自动 DNS 服务发现。用户自定义网络里Docker 会运行一个内嵌 DNS容器内的/etc/resolv.conf通常指向 127.0.0.11。这个地址不是真实网卡而是 Docker 的 DNS 解析入口。当你用容器名访问另一个容器时Docker 内嵌 DNS 会返回对应容器 IP。容器名、网络别名、Compose 里的服务名都能解析。这个机制让多容器项目配置变得简单连接字符串写服务名不写 IP。但要注意DNS 解析只在同一网络内生效。两个容器如果接在不同自定义网络里默认不能通过名称互访也不能直接 IP 互访除非网络之间有路由或容器同时接入多个网络。很多人创建了两个网络然后把 Web 放网络 A数据库放网络 B发现 Web 连不上数据库以为是 DNS 坏了。其实不是是网络隔离在起作用。让 Web 同时接入 A 和 B或者把两者放同一网络问题就解决了。# 创建网络 docker network create appnet # 启动 redis接入 appnet docker run -d --name redis --network appnet redis:7 # 启动 web接入同一网络 docker run -d --name web --network appnet nginx # 在 web 容器里解析 redis docker exec -it web getent hosts redis如果getent hosts redis能返回 IP说明 DNS 正常。如果返回失败先检查两个容器是否在同一网络再检查容器名是否写错。Docker 的 DNS 解析对大小写不敏感但容器名本身要符合规范。重启容器后 IP 会变但名称解析不变这就是不要写死 IP 的原因。3.2 网络隔离与多网络接入Docker 网络隔离靠的是网络命名空间和 iptables 规则。同一自定义网络里的容器默认可以互通不同网络默认隔离。这个默认策略对安全有好处。比如你把前端、后端、数据库分成三个网络前端只能访问后端后端只能访问数据库数据库不直接暴露给前端。这样即使前端被攻破也不能直接连数据库。实现方式就是让后端容器同时接入前端网络和数据库网络充当桥梁。docker network create frontend docker network create backend docker run -d --name api --network frontend myapi docker network connect backend api docker run -d --name db --network backend mysql:8此时 api 能访问 frontend 和 backend 两个网络db 只在 backend。前端容器如果只在 frontend就不能直接访问 db。这个模式在生产环境很常见。注意docker network connect可以给运行中的容器动态加网络不需要重启。移除网络用docker network disconnect。但动态改网络后容器内的 DNS 和路由会更新应用如果缓存了连接或 DNS可能需要重连。还有一个细节容器接入多个网络时默认路由可能只有一个。Docker 会根据网络顺序和网关配置决定默认路由。如果你发现容器访问外网走了错误的网关可以用docker exec进去看ip route。多网络场景下建议显式指定--network和--ip要谨慎固定 IP 会增加运维负担。除非有特殊需求否则让 Docker 自动分配 IP通过名称访问更省心。3.3 手把手用自定义网络跑 Web 和 Redis下面这个例子适合练手。目标一个 Redis 容器和一个 Web 容器Web 能通过服务名连接 Redis宿主机能通过端口访问 Web。先创建自定义网络docker network create demo-net启动 Redisdocker run -d \ --name demo-redis \ --network demo-net \ redis:7启动一个简单的 Web 服务这里用 nginx 模拟实际项目可以换成自己的应用docker run -d \ --name demo-web \ --network demo-net \ -p 8080:80 \ nginx进入 demo-web 测试解析docker exec -it demo-web getent hosts demo-redis docker exec -it demo-web ping -c 2 demo-redis如果镜像里没有 ping可以用getent hosts或curl。能解析出 IP 就说明 DNS 正常。再测试宿主机访问curl http://127.0.0.1:8080如果宿主机访问失败先在宿主机上docker port demo-web看映射再在容器内curl 127.0.0.1:80看服务是否监听。这个分层排查习惯很重要容器内先通再查端口映射再查宿主机防火墙。很多新手一上来就查外部网络其实问题在容器内服务没起来。这个例子还可以扩展成 MySQL 或 Redis 主从。比如你要跑docker安装redis主从主从节点必须在同一自定义网络里从节点配置replicaof redis-master 6379这里的redis-master就是容器名或网络别名。如果你用默认 bridge从节点只能写主节点 IP主节点重启后 IP 变化主从就断了。自定义网络让这种配置更可靠。4. Docker Compose 网络配置多服务项目的连线方式4.1 Compose 默认网络和服务名解析Docker Compose 会自动创建一个默认网络名字通常是项目名_default。项目名默认是当前目录名也可以用-p指定。所有没有显式声明网络的 service 都会接入这个默认网络。在这个网络里每个 service 名称就是 DNS 名称。比如下面这个 compose 文件services: web: image: nginx ports: - 8080:80 redis: image: redis:7执行docker compose up -d后web 容器里可以直接getent hosts redis也能用redis:6379连接。这个体验比手动docker run好很多。Compose 还会给容器设置网络别名服务名、容器名、可能还有项目前缀名都能解析。你不需要写 IP也不需要--link。但有个常见误区Compose 的depends_on只控制启动顺序不保证依赖服务已经就绪。Redis 容器启动了不代表它能接受连接MySQL 容器启动了不代表初始化完成。应用启动太快连不上数据库就退出。解决办法是用健康检查配合depends_on的 condition或者让应用自己重试。网络通不代表服务就绪这是两码事。services: db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: example healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 5s timeout: 3s retries: 10 app: image: myapp depends_on: db: condition: service_healthy4.2 自定义网络、aliases 与 external 网络Compose 里可以显式声明网络控制更细。比如你想让数据库只在内网Web 暴露到宿主机可以这样写services: web: image: nginx networks: - frontend - backend ports: - 8080:80 db: image: mysql:8 networks: - backend environment: MYSQL_ROOT_PASSWORD: example networks: frontend: backend: internal: trueinternal: true表示这个网络没有默认网关不能访问外网。数据库只需要被后端访问不需要出公网这样更安全。aliases可以给服务加额外 DNS 名称。比如数据库服务名是db但应用里想用mysql作为主机名可以加别名services: db: image: mysql:8 networks: backend: aliases: - mysql - database networks: backend:外部网络用external: true。这个场景适合多个 Compose 项目共享同一个网络或者网络由运维提前创建好。比如公司统一创建了shared-net你的 Compose 项目接入它networks: shared: external: true name: shared-net注意外部网络不会随docker compose down删除适合跨项目通信。但也要小心命名冲突和权限问题。生产环境里网络规划应该和部署脚本一起管理不要随手创建一堆名字相似但互相隔离的网络。4.3 生产环境网络配置的几个原则生产环境的 Docker 网络配置核心不是“能通”而是“可控”。第一不要用默认 bridge 跑多服务项目给每个项目或每组服务创建独立自定义网络。第二数据库、缓存、消息队列尽量放 internal 网络不直接映射端口到宿主机。第三需要暴露的服务只映射必要端口能绑 127.0.0.1 就不绑 0.0.0.0。第四容器间连接使用服务名不要写 IP。第五给关键服务加健康检查避免启动顺序问题。第六记录网络子网规划避免和宿主机、虚拟机、办公网冲突。在微服务部署里这些原则尤其重要。你可能有网关、用户服务、订单服务、MySQL、Redis每个服务一套 Compose 或一个 Swarm 服务。网络应该按边界划分对外接入层、业务层、数据层。业务层可以访问数据层接入层只能访问业务层。这样既方便排障也减少攻击面。Docker 网络配置不是孤立的技术点它和部署架构、安全策略、可观测性都相关。还有一点docker compose down默认会删除 Compose 创建的网络但不会删除 external 网络。如果你发现重建后容器连不上先检查网络是否被删掉又重建IP 段是否变化。对于有状态服务网络变化通常不影响数据卷但会影响正在建立的连接。滚动更新时应用要能处理连接中断和 DNS 重新解析。5. 跨主机与特殊网络overlay、macvlan、ipvlan 入门5.1 overlay 网络与 Swarm 模式单机 Docker 网络玩熟之后跨主机通信就该登场了。overlay 网络是 Docker 原生的多主机网络方案通常和 Swarm 模式一起用。初始化 Swarmdocker swarm init然后创建 overlay 网络docker network create --driver overlay my-overlay。不同宿主机上的 Swarm 节点加入同一个 overlay 网络后容器之间可以通过服务名或任务名通信。Docker 会在节点之间建立 VXLAN 隧道把二层流量封装后传输。overlay 的优点是原生、和 Docker 服务集成好。缺点也明显它依赖 Swarm单独用 Docker Compose 跨主机并不直接支持 overlay 服务发现。网络延迟和 MTU 是需要关注的点。VXLAN 封装会增加开销如果宿主机网络 MTU 是 1500overlay 内部可能需要调整否则大包可能被丢弃表现为小请求正常、大文件传输卡住。排查时可以用ping -M do -s测试 MTU。overlay 还要求节点之间特定端口互通防火墙必须放行。公司网络限制多时overlay 可能配不起来。如果你只是两三台机器跑几个容器Kubernetes 或 Swarm 可能太重。可以考虑更简单的方案让容器使用 host 网络通过宿主机端口互连或者用 macvlan 让容器进入同一物理网段。选择方案要看规模、运维能力和安全要求。不要为了“原生”强行上 overlay结果排障时间比开发时间还长。5.2 macvlan 与 ipvlan让容器像物理机一样入网macvlan 和 ipvlan 解决的是“容器要真实 IP”的需求。macvlan 给每个容器分配一个 MAC 地址容器看起来像物理网络中一台独立设备。创建 macvlan 网络通常要指定父接口、子网、网关docker network create -d macvlan \ --subnet192.168.1.0/24 \ --gateway192.168.1.1 \ -o parenteth0 \ pub_net启动容器时接入pub_net容器就能拿到 192.168.1.x 的 IP同网段其他设备可以直接访问它不需要端口映射。这个方案在物联网、网络设备模拟、需要真实 IP 的场景很有用。但它有几个坑第一宿主机默认不能和 macvlan 容器直接通信因为宿主机网卡和 macvlan 接口的 MAC 地址不同交换机可能不回发。解决方法是宿主机也创建一个 macvlan 子接口并配 IP。第二无线网卡通常不支持 macvlan因为无线驱动和 AP 对 MAC 地址有限制。第三交换机端口安全策略可能禁止多个 MAC 地址需要网络管理员配合。ipvlan 和 macvlan 类似但多个容器共享父接口 MAC靠 IP 区分。它在某些无线和虚拟化环境下更友好但兼容性也看内核和驱动。小白阶段不建议在生产环境直接上这两种网络除非你清楚二层网络、ARP、交换机策略。可以先在虚拟机里测试确认宿主机通信、外部访问、重启后 IP 分配都正常再考虑上生产。5.3 选择建议什么时候别碰高级网络我的建议很直接能用自定义 bridge 解决的问题不要用 overlay能用端口映射解决的问题不要用 macvlan能用 Compose 单机编排解决的问题不要上 Swarm。高级网络方案带来能力也带来复杂度和故障面。你一旦引入 overlay 或 macvlan排障就不再只是 Docker 命令还要看 VXLAN、MTU、交换机、ARP、路由协议。小团队没有专职网络运维时越简单的方案越可靠。当然如果业务确实需要跨主机服务发现或者容器必须拥有物理网段 IP那就得用对应方案。关键是先明确需求是需要跨主机通信还是需要真实 IP还是只是想让外部访问需求不同方案完全不同。把需求写成一句话再对照网络驱动选择比看一堆教程有效得多。6. Docker 网络故障排查从内到外一层层剥6.1 五层排查法进程、端口、网络、DNS、防火墙网络不通时我一般按五层排查。第一层进程层容器里服务真的起来了吗用docker logs看日志用docker exec进容器ps或ss -lntp看监听。第二层端口层服务监听的是 0.0.0.0 还是 127.0.0.1很多应用默认只监听 localhost容器外自然访问不到。第三层网络层容器有 IP 吗能 ping 通网关吗docker exec进去看ip addr、ip route再 ping 同网络其他容器。第四层DNS 层容器名能解析吗getent hosts 服务名试试。第五层防火墙和 NAT 层宿主机 iptables、firewalld、ufw 是否拦截端口映射规则是否存在这个顺序能避免乱猜。比如宿主机访问不到容器服务先别查外部网络先确认容器内服务是否监听。如果容器内curl 127.0.0.1:80都不通问题在应用如果容器内通宿主机curl 127.0.0.1:映射端口不通问题在端口映射或宿主机防火墙如果宿主机通外部机器不通问题在宿主机防火墙或云安全组。分层定位每次只改一个变量。# 容器内看监听 docker exec -it web ss -lntp # 容器内测自己 docker exec -it web curl -I http://127.0.0.1 # 宿主机测映射 curl -I http://127.0.0.1:8080 # 查看 iptables NAT 规则 sudo iptables -t nat -L -n6.2 常见报错速查表现象可能原因排查命令解决方法容器无法访问外网DNS 配置错误、iptables 规则丢失、网段冲突docker exec 容器 cat /etc/resolv.conf、iptables -t nat -L检查 daemon.json DNS重启 Docker调整子网容器名 ping 不通用了默认 bridge未接自定义网络docker inspect 容器看 Networks创建自定义网络并接入容器宿主机访问不到映射端口服务监听 127.0.0.1、防火墙拦截、映射写错docker port、ss -lntp、iptables -t nat -L改服务监听 0.0.0.0放行端口检查-p参数端口已被占用宿主机已有进程占用端口ss -lntpgrep 端口Docker Desktop 启动失败提示虚拟化支持未检测BIOS 虚拟化未开、WSL2/Hyper-V 未启用系统信息、Windows 功能进 BIOS 开 VT-x/AMD-V启用 WSL2 或 Hyper-V权限错误/var/run/docker.sock当前用户不在 docker 组groups将用户加入 docker 组并重新登录容器重启后 IP 变化导致连接失败写死 IP未用 DNSdocker inspect使用自定义网络和服务名overlay 大包失败MTU 不匹配ping -M do -s 1472调整 MTU 或网络配置macvlan 容器与宿主机不通宿主机没有 macvlan 子接口ip link创建宿主机 macvlan 接口并配 IPCompose 服务连不上不在同一网络、服务未就绪docker compose ps、docker network inspect统一网络加健康检查和重试这张表可以放在手边。遇到问题先对号入座再深入排查。很多报错看起来吓人实际上就是网络选错、端口写错、防火墙没放行。6.3 我踩过的坑和私房经验第一个坑是默认 bridge 写死 IP。早期我觉得容器 IP 不会变结果每次docker restart后 IP 都可能不同配置文件全要改。后来统一用自定义网络容器名当主机名这个问题再也没出现过。第二个坑是端口映射暴露范围。-p 3306:3306默认监听所有网卡我在测试机上无所谓到了云服务器上就被扫描。后来改成-p 127.0.0.1:3306:3306只允许本机访问需要远程时再通过跳板或专用网络。第三个坑是 Docker Desktop 的虚拟化支持。Windows 上安装 Docker Desktop如果 BIOS 没开虚拟化会提示virtualisation support not detected。这个不是 Docker 网络配置问题但会卡住整个环境。进 BIOS 开 VT-x/AMD-V再启用 WSL2通常能解决。第四个坑是网段冲突。我在公司内网用 172.17.0.0/16 跑 Docker结果和公司某段网络冲突容器访问内部系统时路由异常。后来用docker network create --subnet 10.201.0.0/24显式指定问题消失。第五个坑是防火墙。CentOS 7 默认 firewalld 可能拦截 Docker 映射端口Ubuntu 上 ufw 也可能。Docker 会自己写 iptables 规则但和 firewalld 的规则顺序有时会打架。排查时先临时停防火墙测试确认后再加精确规则不要长期关闭防火墙。第六个坑是容器内 DNS。某些基础镜像的/etc/resolv.conf指向了不可用的 DNS导致容器能通 IP 但解析不了域名。可以在daemon.json里配置dns或者启动容器时--dns 223.5.5.5。最后一个经验网络配置改完后一定要做一次完整验证。容器内访问自己、容器间互访、宿主机访问映射端口、外部机器访问宿主机端口、容器访问外网、容器解析服务名这六项都过了才算真正配好。不要只看docker ps显示 Up 就以为没问题。我在实际项目里每次上线前都会用一个小脚本跑这六项检查能提前发现大部分网络问题。网络这东西平时不出事一出事就是连锁反应提前验证比事后救火轻松得多。