Skip to content

网络、端口映射与数据卷

这篇笔记聚焦 Docker 里另外两条特别容易“会用但没讲透”的主线:

  1. 容器网络
  2. 数据持久化

很多人第一次接触 Docker,最容易遇到的两个问题就是:

  1. 容器里的服务明明启动了,为什么外面访问不到
  2. 容器删掉之后,为什么数据没了

这两个问题背后,分别对应的就是网络和数据卷。


1. 为什么容器网络是一个单独的话题

如果只是本机起一个单进程应用,你可能暂时感觉不到网络的复杂度。
但一旦开始出现这些场景:

  1. 浏览器访问容器里的服务
  2. 一个容器访问另一个容器
  3. 容器访问宿主机服务
  4. 多个服务通过容器协作运行

网络问题就会马上出现。

更贴近实际场景的说法是,容器网络解决的是:容器实例之间、容器和宿主机之间、容器和外部世界之间如何通信。


2. 端口映射到底是什么

端口映射 可以理解成 把宿主机上的某个端口,转发到容器内部服务监听的端口

例如:

bash
docker run -p 8080:80 nginx

这条命令表示:

  1. 宿主机监听 8080
  2. 请求转发到容器里的 80

所以:

宿主机端口容器内端口 不是一回事。

这也是很多人一开始容易混的地方。


3. 为什么服务启动了,外部还是访问不到

最常见的原因通常有这些:

  1. 没有做端口映射
  2. 应用只监听容器内部的特定地址
  3. 映射端口写错了
  4. 宿主机防火墙或安全组拦住了
  5. 访问路径打错了

所以项目里遇到这类问题时,先要分清楚:

  1. 服务是否真的在容器内启动成功
  2. 服务监听的是哪个端口
  3. 有没有做宿主机到容器的端口映射

4. Docker 常见网络模式怎么理解

4.1 bridge

bridge 是最常见的默认网络模式。

它可以理解成 Docker 在宿主机上创建一个桥接网络,让多个容器接入这个虚拟网络并彼此通信

它适合大多数单机多容器场景。

4.2 host

host 模式表示:容器直接共享宿主机网络栈,而不是再做一层独立的网络隔离。

它的特点是:

  1. 端口映射逻辑更直接
  2. 性能路径更短
  3. 但隔离性更弱

4.3 none

none 模式表示:不给容器配置常规网络连接。

这种模式不常见,但适合某些非常特殊的隔离场景。


5. 容器之间怎么通信

如果多个容器在同一个 Docker 网络里,通常可以通过:

  1. 容器名
  2. 服务名
  3. 网络内 IP

进行通信。

这就是为什么很多项目会把应用和数据库容器放进同一个自定义网络里。

例如:

bash
docker network create app-net
docker run -d --name mysql --network app-net mysql:8
docker run -d --name app --network app-net my-app:1.0

这时应用容器通常就可以直接通过 mysql 这个名字访问数据库容器。


6. 数据卷到底是什么

数据卷 可以理解成 独立于容器生命周期之外的一块数据存储位置

它解决的是:

  1. 容器重建后数据不能丢
  2. 某些数据需要长期保留
  3. 宿主机和容器之间需要共享文件

这里一定要记住:容器适合承载应用进程,不天然适合承载长期状态数据。


7. 为什么数据库容器通常都要挂卷

因为数据库最核心的是数据,而不是“容器进程本身还在不在”。

如果数据库数据只写在容器层里,容器一旦删除、重建或迁移,数据就很容易丢失。

所以工程里更常见的做法是:

  1. 数据库存储目录挂载到卷
  2. 日志目录视情况挂载
  3. 上传文件目录独立持久化

8. bind mount 和 volume 有什么区别

8.1 bind mount

bind mount 可以理解成 把宿主机上的某个具体目录或文件,直接挂进容器

它适合:

  1. 本地开发调试
  2. 需要直接编辑宿主机文件
  3. 明确知道要挂哪个宿主机路径

8.2 volume

volume 可以理解成 由 Docker 管理的一种持久化存储

它比手工绑定宿主机路径更抽象,也更适合标准化使用。

把这个区别记住:bind mount 更像直接指定宿主机路径,volume 更像交给 Docker 管理的持久化空间。


9. 一个典型的应用 + 数据库示例

bash
docker network create app-net
docker volume create mysql-data

docker run -d \
  --name mysql \
  --network app-net \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  mysql:8

docker run -d \
  --name app \
  --network app-net \
  -p 8080:8080 \
  my-app:1.0

这组命令表达的是:

  1. 创建一个应用网络
  2. 创建一个独立数据卷
  3. MySQL 容器加入同一个网络,并把数据目录挂到卷上
  4. 应用容器通过网络访问数据库,同时对外暴露端口

10. 工程上最常见的几个误区

10.1 误区一:端口映射后就等于容器里服务一定可用

不是。

端口映射只是打通访问路径的一部分,服务本身是否启动成功仍然要单独确认。

10.2 误区二:容器删了还能保留所有数据

如果没有卷或外部存储,很多数据并不会保留。

10.3 误区三:开发环境和生产环境都直接 bind mount 宿主机路径

开发环境这样做很方便,但生产环境更常见的思路还是:用更可控的卷、对象存储或外部持久化系统。


11. 一句话总结

Docker 的网络和数据卷,本质上是在解决:

容器怎么和外部世界通信,以及容器生命周期结束之后,哪些数据还必须继续被保留下来。

基于 VitePress 构建的个人技术笔记。