【Docker】P4 Docker 网络:掌握 Docker 自定义网络,玩转应用集群
目录
- 为什么我们需要关心 Docker 网络?
- 一种绕路的方法
- 通过IP地址
- 域名解析
- 自定义网络
- 实操:创建并使用自定义网络
- 1. 查看所有网络
- 2. 创建一个自定义网络
- 3. 运行容器并加入网络
- 4. 验证
- 终极实战:构建 Redis 主从复制集群
- 第 1 步:创建网络
- 第 2 步:启动 Master (主) 节点
- 第 3 步:启动 Slave (从) 节点
- 第 4 步:验证主从同步
- 最后的锦囊:我怎么知道用什么配置?
- 总结

大家好!在今天的 Docker 之旅中,我们将深入探讨一个核心且极其重要的话题:Docker 网络。
掌握 Docker 的网络机制,是从“能用”Docker 走向“精通”Docker 的关键一步,它能帮助我们轻松构建和管理复杂的多容器应用,甚至是分布式集群。
为什么我们需要关心 Docker 网络?
在实际开发中,我们的应用很少是“单兵作战”。更常见的情况是,一个应用由多个服务(镜像)组合而成,比如:
- 一个 Web 应用容器(如
Nginx或Node.js)负责处理前端请求。 - 一个 数据库容器(如
MySQL或Redis)负责提供数据存储。
这时,Web 容器就必须能够访问到数据库容器。问题来了:它们如何通信?
一种绕路的方法
新手可能会尝试一种“绕路”的方式:将两个容器的端口都通过 -p 命令映射到宿主机上,然后让 Web 容器通过 宿主机的 IP + 映射的端口 去访问数据库容器。
- 这个流程就像
app1 容器 -> 宿主机 -> app2 容器
但是明显的是,这种方式 效率低下(就好比你要找隔壁部门同事,你先下楼找到公司门口,再找到同事)
通过IP地址
优化整体流程的方式,可以通过“直接找到同事的位置”,即 容器的 IP 地址。
在 docker 中,每当我们启动一个容器时,Docker 会默认将其连接到 docker0 这个网桥,并为其分配一个 内部IP。我们可以通过 docker inspect <容器名> 来查看它的 IP 地址:
$ docker inspect app2
...
"Networks": {"bridge": {..."IPAddress": "172.17.0.3",...}
}
此时,app1 就可以通过这个内部 IP (如 172.17.0.3) 直接访问 app2,实现了 app1 -> app2 的直连,这比绕路宿主机要快得多。但面对的下一个问题是:IP 是动态分配的。一旦 app2 容器被删除并重新创建(这在开发和部署中非常常见),它几乎肯定会获得一个新的 IP 地址。app1 内部硬编码的 IP 地址瞬间失效,应用崩溃。
所以,我们在去寻找这位,隔壁同事的规划,应该去问他在哪儿,而不是他的位置在哪儿。
域名解析
域名解析,我们日常生活中每天都在接触。我们知道输入 www.baidu.com 就能访问到百度首页搜索问题,输入 www.bilibili.com 就能查看UP主的视频… baidu、bilibili 这些就是域名,而从这些域名访问到服务器的第一步就是进行域名解析,解析到服务器集群上。
那么在 docker 中,我们也可以通过设置“域名”的方法,让 app1 并非硬编码到 IP 地址,而是域名,以防止 IP 变化导致的崩溃失效。
而具体实践,请见自定义网络方案。
自定义网络
为了解决上述所有问题,Docker 提供了自定义网络机制。
- 核心优势: 凡是连接到同一个自定义网络的容器,都可以通过它们的 容器名 作为 域名(Hostname)进行互相访问。
Docker 会在这个网络内部署一套 DNS 服务,自动将容器名解析为其当前的内部 IP。
app1想要访问app2?直接连接app2:端口即可。app2重启了,IP 变了?没关系,Docker 的 DNS 会自动更新,app2这个“域名”始终指向正确的新 IP。
这就建立了一套稳定、可靠的服务访问机制。
实操:创建并使用自定义网络
操作非常简单,我们只需要用到 docker network 系列命令。
1. 查看所有网络
docker network ls
你会看到 Docker 默认的 bridge, host, none 等网络。
2. 创建一个自定义网络
我们来创建一个名为 mynet 的新网络(类型默认为 bridge)。
docker network create mynet
3. 运行容器并加入网络
在 docker run 时,使用 --network 参数指定我们刚创建的网络。
# 启动一个 nginx 容器,命名为 app1,加入 mynet
docker run -d -p 88:80 --name app1 --network mynet nginx# 启动另一个 nginx 容器(模拟后端服务),命名为 app2,加入 mynet
# 注意:app2 不需要-p暴露端口到宿主机,因为它只供内部访问
docker run -d --name app2 --network mynet nginx
4. 验证
现在,我们进入 app1 容器,尝试访问 app2:
# 进入 app1 容器的 shell
docker exec -it app1 /bin/bash# 在 app1 容器内部,直接 ping 容器名 app2
root@...:/# ping app2PING app2 (172.19.0.3) 56(84) bytes of data.
64 bytes from app2.mynet (172.19.0.3): icmp_seq=1 ttl=64 time=0.081 ms
...# 尝试用 curl 访问 app2 的 80 端口(nginx 默认端口)
root@...:/# curl app2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
成功了!我们没有使用任何 IP,只用了容器名 app2 就访问到了。
终极实战:构建 Redis 主从复制集群
光说不练假把式。让我们用刚刚学到的网络知识,来搭建一个高可用的 Redis 主从复制(Master-Slave)集群。
我们将使用 bitnami/redis 镜像,它通过环境变量来支持集群配置。

第 1 步:创建网络
首先,为我们的 Redis 集群创建一个专用的网络。
docker network create redis-cluster-net
第 2 步:启动 Master (主) 节点
我们启动第一个 Redis 容器,命名为 redis-master,并将其模式设置为 master。
- 注意:
-v /app/rd1:/bitnami/redis/data是将数据持久化到宿主机的/app/rd1目录。- 请确保宿主机的
/app/rd1目录存在,并且有正确的权限。如果启动失败,请尝试执行mkdir -p /app/rd1 && chmod -R 777 /app/rd1
docker run -d -p 6379:6379 \
-v /app/rd1:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=master \
-e REDIS_PASSWORD=my_strong_password_123 \
--network redis-cluster-net --name redis-master \
bitnami/redis
第 3 步:启动 Slave (从) 节点
接着,我们启动第二个 Redis 容器,命名为 redis-slave。
请看关键配置:
REDIS_REPLICATION_MODE=slave:将其设置为从节点。REDIS_MASTER_HOST=redis-master:这就是魔法发生的地方! 我们直接使用主节点的容器名redis-master作为主机地址。REDIS_MASTER_PORT_NUMBER=6379:主节点的端口。REDIS_MASTER_PASSWORD=...:连接主节点所需的密码。
# 同样,请确保 /app/rd2 目录权限正确
# mkdir -p /app/rd2 && chmod -R 777 /app/rd2docker run -d -p 6380:6379 \
-v /app/rd2:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=slave \
-e REDIS_MASTER_HOST=redis-master \
-e REDIS_MASTER_PORT_NUMBER=6379 \
-e REDIS_MASTER_PASSWORD=my_strong_password_123 \
-e REDIS_PASSWORD=my_strong_password_123 \
--network redis-cluster-net --name redis-slave \
bitnami/redis
第 4 步:验证主从同步
我们已经成功搭建了集群!现在来验证一下。
你可以使用任何 Redis 客户端(如 redis-cli 或 RedisDesktopManager):
- 连接到 Master 节点(宿主机地址:
6379,密码:my_strong_password_123)。 - 设置一个新值:
SET my_key "Hello Docker Network" - 断开连接,然后连接到 Slave 节点(宿主机地址:
6380,密码:my_strong_password_123)。 - 获取这个值:
GET my_key
你会发现,从机上已经自动同步了 Hello Docker Network 这个值。主从复制成功!
最后的锦囊:我怎么知道用什么配置?
你可能会问:“你怎么知道 bitnami/redis 镜像要用 REDIS_REPLICATION_MODE 这些环境变量呢?”
- 答案永远是: 去 Docker Hub 查看官方镜像文档!
在你启动任何容器之前,第一步永远是去 Docker Hub 查找这个镜像的文档。文档会明确告诉你:
- 需要暴露哪些端口?
- 支持哪些环境变量(
-e)来配置它? - 如何持久化数据(
-v)?
所以,学会看技术文档,是重中之重。
总结
今天,我们理解了为什么需要 Docker 网络,以及为什么默认网络不够用。
核心 takeaway 是:在构建多容器应用时,请始终使用自定义网络 (docker network create ...)。
它提供的自动 DNS 和服务发现能力,是构建稳定、可扩展、易于维护的微服务架构的基石。就像我们的 Redis 示例一样,服务之间的依赖关系通过一个简单的容器名就搞定了。
2025.10.31 金融街
