在上一篇 Docker 入门教程中,我们已经掌握了 镜像、容器、Dockerfile、基本运行命令。
但在真实项目中,Docker 的价值并不止于“把应用跑起来”。
当你开始遇到下面这些问题时,就说明你需要深入理解 Docker 网络和数据持久化:
- 多个容器之间如何通信?
- 为什么
localhost在容器里访问不到另一个容器? - 容器删了,数据还能不能保留?
- MySQL、Redis 这类有状态服务,怎么优雅地跑在 Docker 里?
这一篇,我们就系统性地解决这些问题。
一、Docker 网络:容器如何彼此通信?
1.1 为什么容器通信不是“理所当然”的?
在宿主机上,我们习惯了:
localhost:8080
但在 Docker 中:
- 每个容器都有自己的网络命名空间
- 每个容器都像一台“独立的小机器”
这意味着:
容器里的
localhost,指的是容器自己,而不是宿主机,更不是其他容器。
1.2 Docker 默认网络模型(bridge)
安装 Docker 后,默认会创建一个 bridge 网络。
docker network ls
你通常会看到:
- bridge(默认桥接网络)
- host
- none
默认情况下:
docker run nginx
这个容器就会被挂载到 bridge 网络中。
bridge 网络的特点
- 容器之间 可以通信
- 但需要 IP 或显式端口映射
- IP 可能会变化,不适合硬编码
1.3 查看容器网络信息
docker inspect <container_id>
你会看到类似:
"Networks": {
"bridge": {
"IPAddress": "172.17.0.2"
}
}
你确实可以通过这个 IP 访问另一个容器,但这在生产环境是 非常不推荐的。
二、自定义 Docker 网络:让容器“按名字通信”
2.1 创建自定义网络
docker network create my-net
这是一个 用户自定义 bridge 网络,和默认 bridge 最大的区别是:
支持基于容器名的 DNS 解析
2.2 让容器加入同一个网络
docker run -d --name backend --network my-net node-app
docker run -d --name frontend --network my-net nginx
此时:
frontend可以直接访问http://backend:3000- 不需要关心 IP
这是 Docker 官方推荐的容器通信方式。
2.3 一个真实示例:前后端 + API
frontend ---> http://api:8080
api ---> mysql:3306
只要它们在同一个 Docker 网络中:
- 容器名 = 域名
- Docker 自动做 DNS 映射
三、Docker 的三种网络模式对比
| 网络模式 | 特点 | 适用场景 |
|---|---|---|
| bridge | 默认隔离,需端口映射 | 大多数场景 |
| host | 与宿主机共用网络 | 高性能、调试 |
| none | 无网络 | 安全/特殊容器 |
一般结论是:
90% 的项目,用自定义 bridge 网络即可
四、Docker 数据卷(Volumes):容器删了,数据怎么办?
4.1 为什么需要数据卷?
容器的文件系统是:
- 临时的
- 可随时销毁的
docker rm -f mysql
如果数据存在容器里:
数据会直接消失 💥
这对数据库来说是不可接受的。
4.2 Docker 提供了哪几种数据持久化方式?
| 方式 | 描述 | 是否推荐 |
|---|---|---|
| Volume | Docker 管理的存储 | ⭐⭐⭐⭐⭐ |
| Bind Mount | 挂载宿主机目录 | ⭐⭐⭐ |
| tmpfs | 内存存储 | ⭐ |
五、Volume:最推荐的方式
5.1 创建 Volume
docker volume create my-data
docker volume ls
5.2 使用 Volume 启动容器
docker run -d \
--name mysql \
-v my-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8
此时:
- 数据写入
/var/lib/mysql - 实际存储在 Docker 管理的 Volume 中
- 容器删除,数据仍然存在
5.3 验证数据是否持久化
docker rm -f mysql
docker run -d \
--name mysql2 \
-v my-data:/var/lib/mysql \
mysql:8
👉 数据仍然存在
六、Bind Mount:直接挂宿主机目录
docker run -d \
-v /data/mysql:/var/lib/mysql \
mysql:8
优点:
- 数据可直接在宿主机查看
- 适合本地开发、调试
缺点:
- 与宿主机路径强耦合
- 跨平台一致性差
七、网络 + Volume 的组合:真实项目标准姿势
以 Node.js + MySQL 为例:
docker network create app-net
docker volume create mysql-data
docker run -d \
--name mysql \
--network app-net \
-v mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8
docker run -d \
--name api \
--network app-net \
-e DB_HOST=mysql \
node-api
你会发现:
- 网络负责 通信
- Volume 负责 数据安全
- 容器本身可以随意销毁、重建
这正是 Docker 的核心设计哲学。
八、这一篇你应该真正掌握的东西
如果你已经理解并能回答下面问题,说明你真的“进阶”了:
- 为什么容器里访问不了
localhost? - Docker 是如何通过容器名通信的?
- Volume 和 Bind Mount 的本质区别是什么?
- 为什么数据库一定要用 Volume?
文章评论