跳至正文
来两杯美式
返回

Docker 数据持久化与网络:Volume 与容器间通信

By 来两杯美式
发布于

上一篇 《Docker 核心概念与安装》 我们讲了 Docker 的四大概念并跑通了第一个 FastAPI 服务。这一篇我们直面两个「用 Docker 必然遇到」的问题:

  1. 数据持久化:容器删了,数据怎么办?(数据库、上传的模型文件、训练好的 checkpoint)
  2. 容器间通信:一个 Web 容器要访问另一个模型推理容器、一个 PostgreSQL 容器,怎么找得到彼此?

一、为什么需要数据持久化

在传统的软件开发中,数据通常存储在服务器的本地文件系统或数据库中。Docker 容器的出现带来了新的挑战:

容器本身是短暂、无状态的。默认情况下,容器文件系统中的所有数据都会随着容器的删除而永久消失。

但 AI 应用对「数据存活」有强诉求:

Docker 为此提供了多种方案,其中 Volume 是官方最推荐、功能最强的解决方案。


二、什么是 Docker Volume

Docker Volume(卷)是用于持久化容器数据的首选机制。它是一个由 Docker 管理、存在于宿主机文件系统特定部分(Linux 上默认是 /var/lib/docker/volumes/)的目录。

2.1 关键特性

2.2 Volume vs 绑定挂载:不要混淆

容器持久化主要有两种机制,必须分清

机制谁管理路径示例推荐场景
绑定挂载(Bind Mounts)用户指定-v /host/path:/container/path开发环境的代码热加载、配置文件注入
命名卷(Named Volumes)Docker 管理-v my_data:/container/path生产环境的数据库、模型文件、用户上传

简记:能用名字的用名字(命名卷);需要直接看文件的用路径(绑定挂载)。


三、Volume 命令实战

3.1 基础操作

docker volume create redis_data          # 创建一个名为 redis_data 的卷
docker volume ls                        # 列出所有卷
docker volume inspect redis_data        # 查看卷的元数据(含物理路径)
docker volume rm redis_data             # 删除卷
docker volume prune                     # 清理所有未被任何容器使用的卷

注意 1:停止或删除容器,其数据卷依然存在,需要显式删除。 注意 2:如果一个 Volume 正在被任何一个容器(即使是已停止的容器)使用,Docker 会阻止你删除它,必须先删除所有引用该 Volume 的容器。

3.2 命名卷的「项目前缀」

Docker 默认会把卷名前面拼上「项目名_」来避免冲突,比如 Compose 工程 autogpt_platform 下的 clamav-data 卷,最终物理名是 autogpt_platform_clamav-data。这样不同项目可以有同名卷,互不冲突。

如果希望跨项目共享同一个卷,使用 external: true 声明(详见 Compose 篇)。

3.3 在 docker run 中使用卷

# 启动一个 Nginx 容器,把卷挂载到网站根目录
docker run -d --name my-web-server -p 8080:80 \
  -v my-ai-model-storage:/usr/share/nginx/html \
  nginx

把 HTML 文件放进 my-ai-model-storage 卷,访问 http://localhost:8080 就能看到。


四、容器间网络通信

4.1 问题场景

一个典型的 AI 系统至少有三个容器:

它们怎么通信?

4.2 默认网络:bridge

Docker 安装后会自动创建一个 bridge 网络,所有未指定网络的容器都会连上去。默认 bridge 上,容器之间只能通过 IP 互相访问,不能通过容器名——每次重启 IP 都变,很不友好。

4.3 自定义网络:服务名直接通信

Docker 在用户自定义网络中内置了 DNS 解析,容器之间可以直接通过服务名/容器名互相访问。这才是多容器应用应该用的方式。

# 1. 创建自定义网络
docker network create ai-network

# 2. 把容器连到同一个网络
docker run -d --name sentiment-service --network ai-network sentiment-api:1.0
docker run -d --name vector-db         --network ai-network milvus:latest
docker run -d --name frontend-app      --network ai-network nginx

# 3. 在 frontend-app 容器内通过「服务名」直接访问
docker exec -it frontend-app sh
apk add curl
curl http://sentiment-service:8000/    # 直接用名字访问

这就是「服务发现」最朴素的形式——后续 Compose 会自动化这一切。

4.4 端口映射(宿主机 ⇄ 容器)

外部访问容器内的服务,需要把容器的端口「映射」到宿主机:

# -p 宿主机端口:容器端口
docker run -d -p 8080:80 nginx          # 宿主机 8080 -> 容器 80
docker run -d -p 127.0.0.1:8080:80 nginx # 只监听宿主机本地
docker run -d -p 53:53/udp dns-server  # UDP 协议

只暴露需要对外的端口,内部服务只连内部网络,不对外映射,是容器安全的基础。


五、AI 应用中的实战模式

5.1 模型权重持久化

把预训练模型(比如一个 7B 的大模型)放在命名卷里:

docker volume create model-weights
docker run -d --name llm-server \
  -v model-weights:/app/models \
  -p 8000:8000 \
  my-llm-image:1.0

升级推理代码时只换镜像,模型权重不动。启动速度从「每次重新下载 14GB」变成「秒级」。

5.2 用户上传文件

docker volume create user-uploads
docker run -d --name api-server \
  -v user-uploads:/app/uploads \
  -p 8000:8000 \
  my-api:1.0

5.3 日志收集

docker run -d --name app \
  -v app-logs:/var/log/app \
  my-app:1.0

后续可以挂一个日志收集容器,共享同一个 volume 来读日志。


六、小结

这一篇你掌握了:

到这里你已经能跑起「一个完整的多容器 AI 系统」了。但每次都手敲一长串 docker run 命令非常痛苦——下一篇 《Docker Compose 多容器编排:从命令到声明式》,我们把它装进一份 docker-compose.yml,用声明式管理整个应用环境。


分享这篇文章:
通过邮件分享这篇文章✓ 链接已复制
所属专题
Docker
第 3 / 5 篇
查看系列全部文章
  1. 01.Docker 入门:为什么容器化是 AI 时代的必备技能
  2. 02.Docker 核心概念与安装:镜像、容器、仓库、Dockerfile
  3. 03.Docker 数据持久化与网络:Volume 与容器间通信
  4. 04.Docker Compose 多容器编排:从命令到声明式
  5. 05.Docker 集群演进史:Swarm → Compose → Kubernetes

上一篇
Maxwell 数据初始化:maxwell-bootstrap 全量同步实践
下一篇
Docker 核心概念与安装:镜像、容器、仓库、Dockerfile