FEATURED · 精选文章

Docker部署Milvus向量数据库:从Attu可视化到LangChain4j语义检索实战

发布时间 / 2026/9/10 1:56:00
来源 / 创域科博编辑部
栏目 / 资讯中心
Docker部署Milvus向量数据库:从Attu可视化到LangChain4j语义检索实战 最近在给团队搭知识库检索系统文档积累了不少但一直靠关键词like去全文匹配结果就是搜“向量数据库部署”和搜“Docker 安装 Milvus”得到的结果几乎一样语义完全没被利用起来。我先试了 ChromaDB原型阶段确实爽但数据量涨到百万级之后检索性能和稳定性都开始让人不踏实后来试了 pgvector跟 PostgreSQL 绑在一起本来以为能省事结果反而被索引参数、扩展能力这些事拖住了。最后换成了 Milvus 向量数据库配合 Attu 可视化工具整套用 Docker 部署从环境准备到跑通检索整个过程顺畅了很多。这篇文章不写废话直接把我在实际部署中遇到的版本选择、环境坑、编排文件配置以及后来接 Qwen Embedding 和 Java LangChain4j 的完整链路都讲清楚。适合准备用向量库做 RAG、语义检索、知识库问答但还没想清楚怎么在本地或测试环境快速落地的朋友。1. 为什么选 Milvus Attu Docker而不是其他组合1.1 向量数据库选型真实业务场景下的取舍聊选型之前先明确一点ChromaDB、pgvector、Milvus 不是互相替代的关系它们处于不同位置。ChromaDB 更像一个“开发期伴侣”装起来快接口简单跑个小 Demo、几十万向量以内的原型验证它完全够用。但一旦进入需要持续写入、批量导入、定期清理、索引重建、多副本这些生产场景ChromaLDB 的生态和运维能力就偏弱了。pgvector 的优势在于“复用”两个字。如果你本身已经有一套 PostgreSQL业务数据都在里面顺手把向量字段也塞进去短期的确省心。但向量检索和结构化查询的负载特征差异非常大pgvector 在大数据量下的索引构建、召回率稳定性、内存控制这些方面需要自己花不少心思去调。而一旦向量数据增长到需要分片或独立扩容时pgvector 的方案就有点尴尬。Milvus 从一开始就是为向量检索设计的专用数据库。它支持 HNSW、IVF、DiskANN 这些主流索引也支持稀疏向量、动态字段、Iterator 拉取这些能力在做 RAG 混合检索时特别好用。而且 Milvus 2.x 之后的架构把元数据存储、对象存储和计算节点拆开了单机部署不会太重后续要平滑扩容也有路可走。我最终选 Milvus 的一个直接原因是团队后续要做 Java 侧的 LangChain4j 集成Milvus 官方和社区对 Java SDK 的支持成熟度比 ChromaDB 和 pgvector 方案都要好。1.2 Attu 的价值一个让向量库变“可见”的工具刚开始用 Milvus 的时候我一度很崩溃。想查看某个 collection 的字段类型要写个 Python 脚本想确认向量数据有没有真正插入进去还得再写一段查询代码想验证一次检索效果SDK 版本和参数名稍微不对又是一通排查。这个阶段我意识到一个可视化工具比想象中重要。Attu 就是 Milvus 官方的可视化工具基本可以类比成“MySQL 生态中的 Navicat”。它是 Web 界面直接以容器方式跑起来打开浏览器就能看到 collection 列表、字段结构、索引状态、插入的数据记录甚至可以直接在页面上执行向量检索。对于部署环节来说最大的价值是能快速验证 Milvus 服务是不是真的正常工作——不用写任何代码就能确认连接、建集合和数据检索链路。1.3 Docker 部署带来的迁移和回滚红利Milvus 的裸机安装不是不能做但依赖项不少etcd、MinIO、底层动态库还有各种配置文件和环境变量。一旦系统版本变化或者要换一台机器部署整个过程要么重来一遍要么踩到意想不到的兼容性问题。Docker 编排解决的正是这个“环境一致性”问题。用 Docker Compose 部署 Milvus 之后整套环境就是一个docker-compose.yml文件加一个数据卷目录。换机器、给别人复现、做版本升级操作成本都低很多。尤其是升级场景先把数据卷备份好再替换镜像 tag起一个新容器即可。一旦发现问题切回旧镜像就行回滚逻辑非常清晰。2. Docker 部署前的环境检查与版本组合设计2.1 宿主机资源怎么估算Milvus 单机版Standalone虽然叫“单机”但不是一个小内存应用。它至少包含 Milvus 主服务、etcd 元数据引擎、MinIO 对象存储三个进程再加上一个 Attu 容器资源占用就不小了。我自己测试下来的体感参考用途CPU内存磁盘能做什么最小验证2核4G20G SSD起服务、建集合、小规模数据检索开发调试4核8G100G SSD百万级向量、索引构建、混合检索生产小规模8核16G500G SSD多副本、持续写入、在线服务注意Milvus 在导入和建索引时内存占用会陡增尤其是 HNSW 索引这种需要常驻内存的结构。如果你只是拿一台 2G 内存的小机器跑 Docker Desktop大概率会遇到容器 OOM或者 Milvus 容器反复重启。磁盘方面也提醒一句Milvus 的向量数据文件、日志、索引文件都会落到本地卷目录别把卷放在一个很小的系统盘里。我之前有台机器系统盘只有 40G跑了两天数据导入磁盘直接满了。2.2 Docker 与 Compose 安装避坑Linux 环境安装 Docker 比较直接推荐用官方脚本curl -fsSL https://get.docker.com | sh sudo systemctl enable --now docker装完确认一下版本docker --version docker compose version这里有一个老生常谈的坑新版 Docker 的 Compose 命令是docker compose带空格旧版是docker-compose带连字符。如果你的系统里装的是旧版后续命令对应改一下就行但建议直接装新的docker-compose-pluginsudo apt install docker-compose-pluginWindows 上主要用 Docker Desktop它依赖 WSL2。如果启动时报“virtualisation support wasnt detected”多半不是 Docker Desktop 的问题而是系统层面的虚拟化没打开。解决办法是进入 BIOS 开启 CPU 虚拟化Intel 的 VT-x 或 AMD 的 SVM然后在 Windows 功能里勾选“适用于 Linux 的 Windows 子系统”和“虚拟机平台”。改完需要重启Docker Desktop 才能正常启动。另外WSL2 模式下 Docker 的磁盘性能跟 WSL 发行版所在的磁盘有关。如果你把 Docker Desktop 的数据目录放在机械硬盘上向量导入和索引构建会慢得让人怀疑人生尽量选 SSD。2.3 版本组合怎么挑别盲目跟 latestMilvus 的版本迭代节奏不慢latesttag 虽然省心但可能带来两个问题一是镜像本身的配置结构可能变化导致你下载的旧docker-compose.yml不兼容二是 2.5 版本以后和 2.4 版本在部署形态上有一些差异网上搜到的资料很容易对不上号。我建议用 2.4 的稳定版本线组合如下组件镜像和版本说明Milvus 主服务milvusdb/milvus:v2.4.5或者在 2.4.x 范围内选一个稳定版本etcdquay.io/coreos/etcd:v3.5.5Milvus 元数据存储MinIOminio/minio:RELEASE.2023-03-20T20-16-18Z对象存储存放数据文件和索引Attuzilliz/attu:v2.4.5可视化工具版本尽量与 Milvus 主版本对齐Attu 的版本同样不要乱用。它需要解析 Milvus 的元数据格式如果 Attu 版本和 Milvus 版本跨度太大界面可能直接显示空白或者连接异常。3. 用 docker-compose 起一个 Milvus 单机实例3.1 获取官方编排文件并看懂三个核心服务官方针对 Standalone 模式提供了现成的编排文件我习惯把它下载到独立目录方便管理数据卷mkdir -p /data/milvus cd /data/milvus wget https://github.com/milvus-io/milvus/releases/download/v2.4.5/milvus-standalone-docker-compose.yml -O docker-compose.yml文件内容里主要定义了三个服务etcd负责保存 Milvus 内部的元数据比如 collection 定义、分区信息、索引状态、数据段分布等。Milvus 集群模式下 etcd 也是协调核心。minio提供对象存储服务保存向量数据和索引文件。虽然是“单机”部署但 Milvus 内部仍然按照对象存储的逻辑在读写数据。standaloneMilvus 主服务进程通过环境变量ETCD_ENDPOINTS和MINIO_ADDRESS去连接前两个组件。端口方面默认映射关系如下19530Milvus 的 gRPC 服务端口客户端连接走这里。9091健康检查和部分监控指标端口。9000/9001MinIO 的对象存储端口和 Web 控制台端口。2379etcd 端口默认不映射到宿主机只在容器内部网络使用。3.2 持久化目录和自定义配置官方编排文件默认把数据卷放在当前目录下的volumes/volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus这样设计的好处是能通过环境变量DOCKER_VOLUME_DIRECTORY切换数据目录。比如我想把数据统一放到/data/milvus下就在同目录创建一个.env文件DOCKER_VOLUME_DIRECTORY/data/milvus MILVUS_PORT19530然后执行docker compose up -d时Compose 会自动读取.env里的变量。多台机器部署时只要保证.env和数据卷目录一致迁移成本很低。关于 MinIO 账号默认是minioadmin/minioadmin本地测试无所谓但如果有非本机访问的需求记得进 MinIO 控制台改密码。另外Milvus 侧通过环境变量MINIO_ADDRESS连接 MinIO如果改了密码还要给 standalone 服务增加MINIO_ACCESS_KEY和MINIO_SECRET_KEY环境变量否则服务启动后会一直报权限错误。3.3 启动验证与故障快速定位启动命令非常简单docker compose up -d docker compose ps正常情况下会看到三个服务的状态都是Up其中 standalone 的 health 状态在刚启动时可能是starting等十几秒后变成healthy。如果状态一直是unhealthy大概率是 etcd 或 MinIO 没就绪用日志定位docker compose logs standalone --tail100 docker compose logs etcd --tail50确认服务起来之后可以顺手验证一下健康端口curl http://localhost:9091/healthz返回类似OK的响应就代表服务正常。另一个验证方式是用 Python SDKfrom pymilvus import connections, utility connections.connect(hostlocalhost, port19530) print(utility.get_server_version())能打印出版本号就说明这条链路是通的。4. Attu 接入与连接配置实战4.1 两种接入方式手动启动与编排整合Attu 可以单独启动也可以直接写进docker-compose.yml。单独启动的方式适合只想临时看一眼环境的情况docker run -d --name attu \ -p 8000:3000 \ -e MILVUS_URLhttp://localhost:19530 \ zilliz/attu:v2.4.5注意这里MILVUS_URL填的是宿主机角度能访问的 Milvus 地址。如果 Attu 容器和 Milvus 容器在同一个 Docker 网络里可以直接用服务名如果是跨主机就要用宿主机的 IP。我更推荐直接加进编排文件里这样整套环境一次启动管理和迁移都方便attu: image: zilliz/attu:v2.4.5 container_name: attu ports: - 8000:3000 environment: MILVUS_URL: http://standalone:19530 depends_on: - standalone这里的关键点是MILVUS_URL用了服务名standalone因为这两个容器在同一个 Compose 网络里Docker 内部 DNS 会把standalone解析成 Milvus 容器的 IP。如果是手动docker run启动 Attu又没有加到同一个网络填localhost会连不上。改完编排文件后重新加载docker compose up -d浏览器访问http://localhost:8000能看到 Attu 的登录页就说明 UI 起来了。4.2 首次连接 Milvus 的配置细节Attu 打开后需要填 Milvus 的根地址。如果你是浏览器和 Attu 在同一台机器就填http://localhost:19530如果 Milvus 在远程服务器填服务器的内网或公网 IP并且要确保 19530 端口对当前网络可达。这里最容易踩的坑是在服务器上把 Attu 和 Milvus 都用容器跑起来然后在办公室的电脑浏览器里打开 Attu却填了服务器的http://localhost:19530那肯定连不上——浏览器里的localhost指的是你自己电脑不是服务器。Milvus 默认没有开启用户名密码认证登录页的用户名和密码留空直接点连接就能进主界面。4.3 在 Attu 里完成建集合、加索引和检索验证连接成功后我习惯先不做任何代码层的操作直接用 Attu 把整条链路验证一遍。第一步创建一个 collection。字段设计大概像这样字段名类型说明idint64主键自动生成contentvarchar原文文本embeddingfloat_vector1024 维向量创建时需要注意两个参数dimension要和你模型生成的向量维度一致这个错一个数字后面插入数据就会报错metric type选了 COSINE 之后后续每次查询也是用余弦相似度计算。第二步创建索引。在 Attu 的索引管理页面给embedding字段加一个 HNSW 索引参数可以用默认值后续再根据数据分布调M和efConstruction。第三步插入几行测试数据。可以在 Attu 的数据管理页面手动插入也可以先用一段 Python 脚本批量写入再回到 Attu 页面刷新确认数据真的落进去了。第四步就是最有价值的一步在 Attu 的检索页面直接粘贴一个向量设置 topK点击搜索。如果返回结果按相似度排序且字段内容正确说明部署、连接、建集合、索引、查询整条链路都是通的。这一步做完后面接入应用层就很有底气了。5. 部署过程中最容易踩的六个坑5.1 Docker Desktop 提示虚拟化检测不过这个提示在 Windows 上非常常见。现象是启动 Docker Desktop 时直接弹窗说检测不到虚拟化支持然后 Docker 起不来。我遇过的情况有几种BIOS 里确实没开 CPU 虚拟化重启进 BIOS 开启 VT-x/SVM。Windows 功能里的“虚拟机平台”和“适用于 Linux 的 Windows 子系统”没开。装了 WSL2 但默认版本不是 WSL2。处理顺序建议先确认 CPU 虚拟化是否开启再到 Windows 功能里勾选缺失项最后在 PowerShell 里执行wsl --set-default-version 2改完重启。绝大多数情况下这一套能解决。5.2 Milvus 容器一直 unhealthy这是最常见的故障。docker compose ps里 standalone 不是Up而是Up (unhealthy)或者反复重启。先看日志docker compose logs standalone --tail200我遇到过的原因主要有两类。一是 etcd 或 MinIO 没就绪standalone 启动时连不上它们然后在日志里反复打印连接错误。这种情况先看 etcd 和 minio 的健康状态等它们起来后再重启 standalonedocker compose restart standalone二是内存不够。Milvus 启动阶段会加载大量配置和内部组件默认配置可能超出小内存机器的承受能力进程直接被 OOM Killer 干掉。docker compose logs standalone里如果看到 Kernel OOM 相关的记录物理内存加一下或者调小 Milvus 内部缓存参数。5.3 卷目录大小不够Milvus 的数据全部落在数据卷里很多人在docker compose up -d之后就再也不管了直到某天容器起不来查了半天才发现是磁盘满了。尤其是在测试阶段反复导入、删除向量数据磁盘空间的消耗速度比想象中快。建议把卷目录放到单独的数据盘并且定期检查du -sh /data/milvus/volumes/*如果只是想验证功能不用保留历史数据可以直接清理卷目录再重建但这会删掉所有集合和数据慎用。5.4 Attu 能打开但连不上 MilvusAttu 页面能打开说明 Attu 服务本身没问题。连接失败时先分清是哪个角度连不上是 Attu 容器连不上 Milvus还是浏览器连不上 Attu两个链路的问题不一样。如果MILVUS_URL填的是http://localhost:19530而 Attu 是独立容器它内部的localhost指向容器自己当然连不上。正确做法是使用同一个 Docker 网络中的服务名或者填宿主机 IP。另一个隐蔽问题是防火墙。Linux 服务器上如果开启了防火墙19530 端口可能对外不可达。放行命令参考sudo ufw allow 19530/tcp sudo ufw allow 8000/tcp放行之后再用nc -zv 服务器IP 19530从客户端侧测一下通不通。5.5 Milvus 端口与本地服务冲突本地开发机经常会有各种服务占着 19530。如果你的机器上已经有一个程序占用该端口Milvus 容器启动时端口映射会失败但 Compose 可能不会立刻报错要等日志输出才看得到。解决办法是改用其他宿主机端口MILVUS_PORT19531 docker compose up -d修改之后客户端连接地址也要同步更新。5.6 版本升级后数据不可用Milvus 的版本升级不是简单替换镜像 tag 就能保证平滑的。Milvus 2.4 到 2.5 的数据目录和元数据格式不完全一致在测试环境直接升级可能旧数据读不出来。如果你只是做本地验证重来一次也无所谓。但如果里面已经有重要的测试数据升级前一定先备份整个volumes目录至少备份 etcd 和 minio 两块。升级后第一时间在 Attu 里检查 collection 是否存在、索引是否正常。6. 与 Qwen Embedding 和 LangChain4j 打通实现 Java 侧的入库与检索6.1 用 Qwen 的 Embedding 模型生成文本向量部署完 Milvus最终目的是做语义检索。Embedding 模型我这边用的是 Qwen 的text-embedding-v3它支持通过 OpenAI 兼容接口调用代码写起来很方便。一个简单的调用示例curl -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings \ -H Authorization: Bearer YOUR_DASHSCOPE_API_KEY \ -H Content-Type: application/json \ -d { model: text-embedding-v3, input: Milvus向量数据库的Docker部署, dimensions: 1024 }返回的data[0].embedding就是 1024 维的向量。这里有两个要点第一dimensions必须和 Milvus collection 里定义的dimension一致第二同一个知识库里的所有文本都应该用同一个模型生成向量混用不同的 Embedding 模型会导致检索效果离谱。6.2 LangChain4j 最小可运行示例Java 侧我用的是 LangChain4j它提供了 Milvus 的集成模块。在pom.xml里加上依赖dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version0.35.0/version /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-milvus/artifactId version0.35.0/version /dependencyEmbedding 模型和向量存储的配置OpenAiEmbeddingModel embeddingModel OpenAiEmbeddingModel.builder() .apiKey(System.getenv(DASHSCOPE_API_KEY)) .baseUrl(https://dashscope.aliyuncs.com/compatible-mode/v1) .modelName(text-embedding-v3) .dimensions(1024) .build(); MilvusEmbeddingStore embeddingStore MilvusEmbeddingStore.builder() .host(localhost) .port(19530) .collectionName(qa_docs) .dimension(1024) .build();写入文本和向量的流程TextSegment segment TextSegment.from(Milvus是一个开源的向量数据库); Embedding embedding embeddingModel.embed(segment).content(); embeddingStore.add(embedding, segment);检索时只需要把查询文本也转成向量然后搜索Embedding queryEmbedding embeddingModel.embed(什么是向量数据库).content(); ListEmbeddingMatchTextSegment matches embeddingStore.search(queryEmbedding, 5); for (EmbeddingMatchTextSegment match : matches) { System.out.println(match.score() - match.embedded().text()); }这段代码跑通之后你的 Java 服务就已经具备“文本入库到 Milvus”和“语义检索”的能力了。6.3 混合检索与重排的注意点如果你的业务不是简单的向量召回而是想走“多路召回 重排”这条路线LangChain4j 自带的MilvusEmbeddingStore就有点不够用了。它封装的是标准的向量相似度检索而混合检索需要同时执行多个检索条件再把多路结果合并排序。Milvus 2.
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻