Docker: Docker网络基础

最后更新:2026-08-26

容器网络是 Docker 最容易让人困惑的部分——直到你理解了"每个容器有自己的 localhost"。

1. 你将学到


2. 一个开发者的真实故事

(1) 痛点:容器间 localhost 连不上

Alice 的 Web 应用和数据库在两个容器里,Web 容器用 localhost:5432 连不上数据库。她困惑了 2 小时:"明明数据库在 5432 端口监听,为什么连不上?"

(2) 容器网络隔离的解法

Bob 说:"每个容器有自己的 localhost。Web 容器的 localhost 是 Web 自己,不是数据库。要用容器名或自定义网络通信。"

BASH
# Create a custom network for inter-container communication
docker network create app-net

# Start containers on the same network
docker run -d --name db --network app-net -e POSTGRES_PASSWORD=secret postgres:15
docker run -d --name web --network app-net -p 8080:5000 myapp

# Web connects to db:5432 (not localhost:5432)

(3) 收益:网络问题 2 小时→5 分钟

理解了容器网络模型后,Alice 的网络问题从 2 小时排查降到 5 分钟配置。


3. Docker 四种网络模式

(1) 模式概览

100%
graph TB
    subgraph Bridge["Bridge Mode (default)"]
        B1["Container A<br/>172.17.0.2"] --- B2["docker0 bridge<br/>172.17.0.1"]
        B2 --- B3["Container B<br/>172.17.0.3"]
        B2 --- B4["Host eth0<br/>via NAT"]
    end
    subgraph Host["Host Mode"]
        H1["Container"] --- H2["Host Network Stack<br/>Shares all ports"]
    end
    subgraph None["None Mode"]
        N1["Container<br/>Loopback only"]
    end
    subgraph Overlay["Overlay Mode"]
        O1["Container A<br/>Host 1"] -.- O2["Container B<br/>Host 2"]
    end

(2) 四种模式对比

维度 Bridge Host None Overlay
隔离性 独立网络栈 共享主机网络 完全隔离 跨主机虚拟网络
端口映射 需要 -p 不需要 不可用 内置路由
性能 中(NAT 开销) 高(直接访问) - 中(VXLAN 封装)
DNS 解析 仅自定义 bridge 无(共享主机) ✅ 内置
跨主机
适用场景 单机多容器 高性能网络 安全隔离/调试 Docker Swarm 集群

4. Bridge 网络详解

(1) 默认 bridge vs 自定义 bridge

维度 默认 bridge 自定义 bridge
DNS 解析 ❌ 只能用 IP ✅ 用容器名通信
容器隔离 所有容器同一网络 按网络分组隔离
推荐度 ⭐(兼容旧版) ⭐⭐⭐(推荐)
创建方式 Docker 自动创建 docker network create

▶ 示例:创建自定义 bridge 网络(难度⭐)

BASH
# Create a custom bridge network
docker network create --driver bridge app-net

# Verify
docker network ls | grep app-net
docker network inspect app-net

▶ 示例:容器间 DNS 解析(难度⭐⭐)

BASH
# Start two containers on the same custom network
docker run -d --name db --network app-net \
  -e POSTGRES_PASSWORD=secret postgres:15-alpine
docker run -d --name api --network app-net \
  nginx:alpine

# DNS resolution: api can reach db by name
docker exec api ping -c 2 db
💻 输出:

TEXT 📖 仅展示
PING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.100 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.050 ms
📌 重点: 自定义 bridge 网络自动为每个容器注册 DNS 记录。容器名就是主机名——db 解析为数据库容器的 IP。这就是为什么 Phase 1 的 LEMP 项目中 fastcgi_pass lemp-php:9000 能工作。

▶ 示例:网络隔离验证(难度⭐⭐)

BASH
# Create two separate networks
docker network create frontend-net
docker network create backend-net

# Frontend container
docker run -d --name web --network frontend-net nginx:alpine

# Backend container
docker run -d --name api --network backend-net nginx:alpine

# web CANNOT reach api (different networks)
docker exec web ping -c 2 -W 2 api
# Output: ping: bad address 'api'

# Connect web to backend-net (now it can reach api)
docker network connect backend-net web
docker exec web ping -c 2 api
# Output: PING api (172.19.0.2): 64 bytes

5. Host 网络模式

▶ 示例:Host 模式运行容器(难度⭐⭐)

BASH
# Run with host network (shares host's network stack)
docker run -d --name host-nginx --network host nginx:alpine

# No port mapping needed - nginx directly listens on host's port 80
curl http://localhost:80
⚠️ 注意: Host 模式下容器直接使用主机端口,不需要 -p 映射。但端口冲突风险高——如果主机 80 端口已被占用,容器启动会失败。生产环境慎用。


6. 端口映射原理

(1) 三种端口暴露方式

方式 语法 说明
-p host:container -p 8080:80 指定映射
-P -P 随机映射到 EXPOSE 声明的端口
--network host --network host 无需映射(共享主机网络)

▶ 示例:docker network inspect 查看网络详情(难度⭐⭐)

BASH
# Inspect network configuration
docker network inspect app-net
💻 输出(节选):

TEXT 📖 仅展示
[
  {
    "Name": "app-net",
    "Driver": "bridge",
    "IPAM": {
      "Config": [{"Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"}]
    },
    "Containers": {
      "a1b2c3d4...": {"Name": "db", "IPv4Address": "172.18.0.2"},
      "e5f6a7b8...": {"Name": "api", "IPv4Address": "172.18.0.3"}
    }
  }
]

7. 完整示例:三层网络架构

BASH
# ============================================
# Complete walkthrough: Three-tier network architecture
# Frontend / Backend / Database isolation
# ============================================

# 1. Create three networks
docker network create frontend-net
docker network create backend-net
docker network create db-net

# 2. Start database (only on db-net)
docker run -d --name db \
  --network db-net \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=myapp \
  postgres:15-alpine

# 3. Start API server (backend-net + db-net)
docker run -d --name api \
  --network backend-net \
  -e DATABASE_URL="postgresql://postgres:secret@db:5432/myapp" \
  myapp-api:1.0

# Connect API to db-net so it can reach the database
docker network connect db-net api

# 4. Start Nginx (frontend-net + backend-net)
docker run -d --name web \
  --network frontend-net \
  -p 8080:80 \
  -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf \
  nginx:1.25-alpine

# Connect Nginx to backend-net so it can reach the API
docker network connect backend-net web

# 5. Verify connectivity
docker exec web ping -c 1 api     # web → api ✅
docker exec api ping -c 1 db      # api → db ✅
docker exec web ping -c 1 -W 1 db # web → db ❌ (not on db-net)

# 6. Clean up
docker stop web api db
docker rm web api db
docker network rm frontend-net backend-net db-net

❓ 常见问题

Q 两个容器不在同一个网络能通信吗?
A 默认不能。每个网络是独立的隔离域。要让容器 A 访问网络 B 中的容器 C,需要用 docker network connect 将 A 加入网络 B。一个容器可以同时属于多个网络。
Q host 网络模式有什么风险?
A 两个主要风险:① 端口冲突——容器直接监听主机端口,已有服务占用时启动失败;② 安全——容器可访问主机所有网络接口,包括 localhost 上的内部服务。仅在需要极致网络性能时使用 host 模式。
Q 容器 IP 会变吗?
A 会。容器重启后 IP 可能变化(尤其是非用户定义子网)。这就是为什么应该用容器名(DNS 解析)而不是 IP 地址通信。自定义 bridge 网络的 DNS 自动维护容器名→IP 的映射。
Q 怎么限制容器的网络访问?
A 三种方式:① 用多个网络隔离(推荐)——数据库只在 db-net,前端无法直接访问;② iptables 规则(高级);③ --icc=false 禁用默认 bridge 的容器间通信(不推荐,用自定义网络更好)。
Q 跨主机的容器怎么通信?
A 单机 Docker 无法直接跨主机。方案:① Overlay 网络(需要 Docker Swarm 或手动配置 etcd);② 端口映射 + 主机 IP;③ 第三方网络插件(Weave/Calico)。Docker Swarm 的 Overlay 网络是最简单的跨主机方案(Phase 4 第 20 课)。

📖 小节


📝 作业

  1. 基础题(难度⭐):创建自定义 bridge 网络,启动两个 Nginx 容器,验证容器名 DNS 解析(docker exec A ping B)。
  2. 进阶题(难度⭐⭐):创建两个不同网络,各放一个容器,验证跨网络容器无法 ping 通。然后用 docker network connect 连通。
  3. 挑战题(难度⭐⭐⭐):用 docker network inspect 查看自定义网络的 IPAM 配置和容器列表,理解 Docker 内部网络路由机制。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏