共计 5696 个字符,预计需要花费 15 分钟才能阅读完成。
文章目录[显示]
🌐 Docker 网络入门:让容器互相通信
Docker 30 天实战系列 · Day 7
你是否遇到过这样的困惑:
- 🤔 " 容器之间怎么互相访问?" —— 启动了多个容器,却不知道怎么让它们通信
- 🌐 " 端口映射到底怎么用?" ——
-p 8080:80这些参数让人头晕 - 🔗 " 微服务架构下容器怎么互联?" —— 前端、后端、数据库该如何配合
今天,我们将揭开 Docker 网络的神秘面纱,让你彻底掌握容器间通信的核心技能。
本文你将学到
完成今天的学习后,你将能够:
- ✅ 理解 Docker 的 4 种网络模式及其适用场景
- ✅ 创建自定义网络实现容器间通信
- ✅ 掌握端口映射的各种用法
- ✅ 搭建一个完整的多容器应用架构
阅读时间:约 15-20 分钟
实操时间:约 20-30 分钟
难度等级:⭐⭐⭐☆☆
前置准备
环境要求
| 项目 | 要求 | 检查命令 |
|---|---|---|
| Docker | 20.10+ | docker --version |
| 操作系统 | macOS / Windows / Linux | – |
| 前置知识 | Day 1-6 内容 | – |
环境检查
# 确认 Docker 正在运行
docker ps
# 查看当前网络列表
docker network ls
预期输出:
NETWORK ID NAME DRIVER SCOPE
xxxxxxxxxxxx bridge bridge local
xxxxxxxxxxxx host host local
xxxxxxxxxxxx none null local
如果看到这三个默认网络,说明环境准备就绪。
清理旧容器
为了避免端口冲突,先清理之前的实验容器:
# 停止并删除所有运行中的容器(谨慎使用)docker rm -f $(docker ps -aq) 2>/dev/null || true
Docker 网络模式详解
Docker 提供了 4 种主要的网络模式,每种模式适用于不同的场景。
网络模式对比
┌─────────────────────────────────────────────────────────────┐
│ Docker 网络模式 │
├─────────────┬───────────────────────────────────────────────┤
│ bridge │ 默认模式,容器有独立 IP,通过 NAT 访问外网 │
├─────────────┼───────────────────────────────────────────────┤
│ host │ 容器直接使用宿主机网络,无网络隔离 │
├─────────────┼───────────────────────────────────────────────┤
│ none │ 容器没有网络,完全隔离 │
├─────────────┼───────────────────────────────────────────────┤
│ 自定义 │ 用户创建的网络,推荐生产使用 │
└─────────────┴───────────────────────────────────────────────┘
模式选择指南
| 网络模式 | 隔离性 | 性能 | 适用场景 |
|---|---|---|---|
| bridge (默认) | 中 | 好 | 单机多容器、开发测试 |
| host | 无 | 最佳 | 性能敏感的网络应用 |
| none | 最强 | – | 安全隔离、离线计算 |
| 自定义网络 | 可控 | 好 | 生产环境推荐 |
实战一:探索默认 Bridge 网络
步骤 1:启动测试容器
# 启动两个 nginx 容器
docker run -d --name web1 nginx:alpine
docker run -d --name web2 nginx:alpine
步骤 2:查看容器 IP 地址
# 查看 web1 的 IP
docker inspect web1 --format '{{.NetworkSettings.IPAddress}}'
# 查看 web2 的 IP
docker inspect web2 --format '{{.NetworkSettings.IPAddress}}'
预期输出:
172.17.0.2
172.17.0.3
步骤 3:测试容器间通信
# 进入 web1 容器,尝试访问 web2
docker exec web1 ping -c 3 172.17.0.3
预期输出:
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.123 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.089 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.092 ms
✅ IP 直连成功! 但是 …
步骤 4:发现问题 – 无法通过容器名通信
# 尝试用容器名访问
docker exec web1 ping -c 3 web2
预期输出:
ping: bad address 'web2'
❌ 失败了! 默认 bridge 网络不支持容器名解析。
这就是为什么我们需要 自定义网络。
清理
docker rm -f web1 web2
实战二:创建自定义网络(推荐方式)
自定义网络解决了默认 bridge 的两个问题:
- 容器名自动解析 – 可以直接用容器名通信
- 更好的隔离性 – 不同网络的容器默认无法互访
步骤 1:创建自定义网络
# 创建名为 myapp-network 的网络
docker network create myapp-network
验证创建成功:
docker network ls
预期输出:
NETWORK ID NAME DRIVER SCOPE
xxxxxxxxxxxx bridge bridge local
xxxxxxxxxxxx host host local
xxxxxxxxxxxx myapp-network bridge local <-- 新创建的
xxxxxxxxxxxx none null local
步骤 2:在自定义网络中启动容器
# 启动两个容器,加入同一个网络
docker run -d --name web1 --network myapp-network nginx:alpine
docker run -d --name web2 --network myapp-network nginx:alpine
步骤 3:验证容器名解析
# 用容器名直接访问
docker exec web1 ping -c 3 web2
预期输出:
PING web2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.089 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.078 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.082 ms
✅ 成功! 容器名自动解析为 IP 地址。
步骤 4:测试 HTTP 访问
# 从 web1 访问 web2 的 nginx 服务
docker exec web1 wget -qO- http://web2
预期输出(nginx 欢迎页面的 HTML):
Welcome to nginx!
...
✅ 服务间通信成功!
实战三:端口映射详解
端口映射让外部网络可以访问容器内的服务。
端口映射语法
-p [宿主机 IP:]宿主机端口: 容器端口[/ 协议]
常用端口映射方式
# 方式 1:映射到所有网卡的指定端口
docker run -d -p 8080:80 nginx:alpine
# 访问:http://localhost:8080
# 方式 2:只绑定到 localhost(更安全)docker run -d -p 127.0.0.1:8081:80 nginx:alpine
# 只能本机访问:http://127.0.0.1:8081
# 方式 3:随机端口映射
docker run -d -p 80 nginx:alpine
# Docker 自动分配宿主机端口
# 方式 4:映射 UDP 端口
docker run -d -p 53:53/udp dns-server
查看端口映射
# 查看所有容器的端口映射
docker ps
# 查看特定容器的端口
docker port <容器名>
端口映射示例
# 启动一个 nginx,映射到 8080 端口
docker run -d --name mynginx -p 8080:80 nginx:alpine
# 查看映射
docker port mynginx
预期输出:
80/tcp -> 0.0.0.0:8080
访问测试:
打开浏览器访问 http://localhost:8080,应该看到 nginx 欢迎页面。
实战四:搭建完整的多容器应用
让我们搭建一个真实的应用架构:Nginx (前端) + Redis (缓存)
架构图
┌─────────────────┐
│ 用户浏览器 │
└────────┬────────┘
│
▼ :8080
┌────────────────────────────────────────────────────────────┐
│ 宿主机 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ myapp-network (自定义网络) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ nginx │ ──────> │ redis │ │ │
│ │ │ :80 │ │ :6379 │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ │ │
│ └─────────┼────────────────────────────────────────────┘ │
│ │ │
└────────────┼───────────────────────────────────────────────┘
│
▼
端口映射 8080:80
步骤 1:准备网络和容器
# 确保网络存在
docker network create myapp-network 2>/dev/null || true
# 启动 Redis
docker run -d \
--name redis \
--network myapp-network \
redis:alpine
# 启动 Nginx(对外暴露端口)docker run -d \
--name nginx \
--network myapp-network \
-p 8080:80 \
nginx:alpine
步骤 2:验证容器状态
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
预期输出:
NAMES STATUS PORTS
nginx Up 10 seconds 0.0.0.0:8080->80/tcp
redis Up 15 seconds 6379/tcp
步骤 3:验证内部通信
# 从 nginx 容器 ping redis
docker exec nginx ping -c 2 redis
# 测试 Redis 连接(使用 redis-cli)docker exec redis redis-cli ping
预期输出:
PONG
步骤 4:验证外部访问
# 测试外部访问 nginx
curl http://localhost:8080
或者打开浏览器访问 http://localhost:8080
✅ 多容器应用搭建成功!
网络管理常用命令
网络操作命令速查
# 列出所有网络
docker network ls
# 创建网络
docker network create <网络名>
# 查看网络详情
docker network inspect <网络名>
# 删除网络
docker network rm <网络名>
# 删除所有未使用的网络
docker network prune
# 将容器连接到网络
docker network connect <网络名> <容器名>
# 将容器从网络断开
docker network disconnect <网络名> <容器名>
实用技巧
查看网络中的所有容器:
docker network inspect myapp-network --format '{{range .Containers}}{{.Name}} {{end}}'
让已运行的容器加入网络:
# 容器可以同时属于多个网络
docker network connect myapp-network 现有容器名
🤔 常见问题
Q1:容器之间 ping 不通怎么办?
A:按以下步骤排查:
# 1. 确认两个容器在同一个网络
docker inspect 容器 1 --format '{{.NetworkSettings.Networks}}'
docker inspect 容器 2 --format '{{.NetworkSettings.Networks}}'
# 2. 如果不在同一网络,手动连接
docker network connect myapp-network 容器名
Q2:端口已被占用怎么办?
A:
# 查看端口占用
lsof -i :8080
# 或者使用其他端口
docker run -d -p 8081:80 nginx:alpine
Q3:容器重启后 IP 会变吗?
A:会变!这就是为什么要用自定义网络 + 容器名访问,而不是硬编码 IP。
# 推荐:用容器名(不会变)redis://redis:6379
# 不推荐:用 IP(可能会变)redis://172.18.0.3:6379
Q4:如何查看容器的网络配置?
A:
# 查看完整网络配置
docker inspect 容器名 --format '{{json .NetworkSettings}}' | jq
# 或者简化版
docker inspect 容器名 | grep -A 20 NetworkSettings
Q5:host 网络模式什么时候用?
A:当你需要 最高网络性能 且不需要网络隔离 时:
# 使用 host 网络(Linux 下有效)docker run -d --network host nginx:alpine
# 容器直接使用宿主机 80 端口
curl http://localhost
⚠️ 注意:host 模式在 macOS/Windows 的 Docker Desktop 上行为不同。
📚 本文总结
核心要点
-
4 种网络模式:
bridge:默认模式,适合开发测试host:最高性能,无隔离none:完全隔离- 自定义网络:生产推荐 ⭐
-
自定义网络的优势:
- ✅ 容器名自动 DNS 解析
- ✅ 更好的网络隔离
- ✅ 可以指定子网和网关
-
端口映射:
-p 8080:80:映射到所有网卡-p 127.0.0.1:8080:80:只绑定本地-p 80:随机端口
-
最佳实践:
- 始终使用自定义网络
- 通过容器名通信,不要用 IP
- 只暴露必要的端口
命令速查表
| 命令 | 说明 |
|---|---|
docker network ls |
列出网络 |
docker network create mynet |
创建网络 |
docker network inspect mynet |
查看网络详情 |
docker network rm mynet |
删除网络 |
docker run --network mynet |
指定网络启动 |
docker network connect mynet 容器 |
连接容器到网络 |
实验清理
完成今天的学习后,清理实验环境:
# 删除所有实验容器
docker rm -f nginx redis web1 web2 mynginx 2>/dev/null
# 删除自定义网络
docker network rm myapp-network custom-net 2>/dev/null
下一步学习
今天我们学习了 Docker 网络的基础知识。这是构建复杂应用的关键技能!
明天预告:Day 8 - 编写你的第一个 Dockerfile:Node.js 应用容器化
我们将学习如何编写 Dockerfile,把自己的应用打包成 Docker 镜像。
第一周回顾:
- ✅ Day 1:Docker 是什么
- ✅ Day 2:Docker 安装
- ✅ Day 3:第一个容器
- ✅ Day 4:镜像管理
- ✅ Day 5:常用容器实战
- ✅ Day 6:数据持久化
- ✅ Day 7:Docker 网络(今天)
🎉 恭喜完成第一周的学习! 你已经掌握了 Docker 的核心基础知识。
💬 互动时间
今日思考:在你的项目中,哪些服务需要互相通信?你会如何设计它们的网络架构?
今日作业:
- 创建一个自定义网络
- 在网络中启动 nginx 和 redis
- 验证容器名可以互相访问
- 尝试端口映射,从浏览器访问 nginx
在评论区分享你的实践结果:
- 💡 你遇到了什么问题?
- ✅ 你是怎么解决的?
- 🎯 你对 Docker 网络还有什么疑问?
如果这篇文章对你有帮助:
- 👍 点个「赞」和「在看」
- 🔄 分享给需要的朋友
- 💬 评论区交流心得
📖 相关资源
官方文档:
系列文章:
关于本系列
这是「Docker 30 天实战系列」的第 7 篇文章。
本系列将用 30 天时间,带你从零基础到实战部署,系统掌握 Docker 容器技术:
- Week 1:基础入门 ✅ 完成!
- Week 2:镜像构建(Dockerfile、优化、最佳实践)
- Week 3:容器编排(Docker Compose、多容器)
- Week 4:生产实践(安全、性能、CI/CD)
🔔 关注公众号,不错过每一篇干货!
下周见!我们将进入 Dockerfile 编写的精彩世界 🚀
作者:Docker 实战系列
发布日期:2026-02-16
系列进度:7/30
🐳 Happy Dockering!