Ubuntu 20.04 上构建你的专属向量数据库:从Docker部署到可视化运维全指南

在AI应用开发的世界里,向量数据库正迅速成为处理非结构化数据、赋能语义搜索和推荐系统的核心基础设施。对于许多开发者而言,Milvus这个名字已经不再陌生,它以其开源、高性能和云原生的特性,成为了构建向量检索应用的热门选择。然而,当面对一个全新的技术栈时,如何快速、稳定地在自己的开发环境或服务器上将其“跑起来”,往往是第一个需要跨越的障碍。如果你手头有一台运行Ubuntu 20.04的机器,并且希望用最简洁的方式,从零开始搭建一个功能完整的Milvus服务,甚至还能通过一个直观的界面来管理它,那么这篇文章正是为你准备的。

我们将完全基于Docker容器技术,避开复杂的源码编译和环境依赖,通过一系列清晰、可复制的命令,带你完成从环境准备、Milvus核心服务部署、数据持久化配置,到最终部署一个轻量级可视化管理界面的全过程。无论你是对Docker命令尚不熟悉的入门者,还是希望寻找一份标准化部署清单的资深工程师,这里的内容都将力求详实、步骤明确,并穿插必要的原理解释和避坑指南,让你不仅“知其然”,更能“知其所以然”。

1. 环境准备与Docker基础

在开始部署Milvus之前,确保你的Ubuntu 20.04系统已经准备就绪。一个干净、稳定的基础环境是后续所有操作成功的前提。

1.1 系统更新与依赖检查

首先,打开你的终端。建议使用一个具有sudo权限的用户账户进行操作。第一步永远是更新系统的软件包列表,并升级已有的软件到最新版本,这能帮助我们获取最新的安全补丁和系统组件。

sudo apt update && sudo apt upgrade -y

这个过程可能会花费几分钟时间,取决于你的网络速度和需要更新的软件包数量。完成后,我们可以检查一些基础依赖,例如curl和wget,它们通常用于从网络下载文件。

which curl wget

如果命令返回了路径,说明已安装;如果没有,可以通过sudo apt install curl wget -y来安装。

1.2 Docker引擎的安装与配置

Milvus官方强烈推荐使用Docker进行部署,这能最大程度地保证环境的一致性,并简化依赖管理。Ubuntu 20.04的官方仓库中可能不是最新的Docker版本,因此我们采用Docker官方提供的仓库进行安装。

1. 卸载旧版本(如果存在) 为了避免冲突,先清理可能存在的旧版本Docker。

sudo apt remove docker docker-engine docker.io containerd runc -y

2. 安装依赖工具包 这些工具允许apt通过HTTPS使用仓库。

sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y

3. 添加Docker官方GPG密钥 此密钥用于验证下载软件包的完整性。

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

4. 设置稳定版仓库 将Docker的稳定版仓库地址添加到系统的软件源列表中。

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

5. 安装Docker引擎 更新软件包列表并安装Docker CE(社区版)、CLI以及Containerd。

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io -y

6. 验证安装并管理服务 安装完成后,启动Docker服务并设置开机自启。运行一个简单的hello-world镜像来验证安装是否成功。

sudo systemctl start docker
sudo systemctl enable docker
sudo docker run hello-world

如果看到“Hello from Docker!”等欢迎信息,说明Docker已经正确安装并可以运行容器了。

提示:默认情况下,运行Docker命令需要sudo权限。为了方便日常开发,可以将当前用户加入docker用户组,之后运行命令就无需每次都加sudo了。执行sudo usermod -aG docker $USER,然后退出终端重新登录即可生效。

2. 部署Milvus核心服务

有了Docker环境,我们就可以开始部署Milvus了。这里我们选择部署一个CPU版本的Milvus,它足以满足大多数开发、测试和小规模生产场景的需求。

2.1 拉取Milvus镜像

Docker Hub上提供了官方维护的Milvus镜像。虽然原始资料中提到了一个较旧的特定版本(1.1.0),但为了获得更好的功能特性和稳定性,我们建议拉取一个更新的稳定版本。你可以访问Milvus的Docker Hub页面查看所有可用标签。

例如,我们拉取一个较新的CPU版本镜像(请根据实际需要选择版本):

docker pull milvusdb/milvus:2.3.3-cpu-latest

拉取镜像的过程需要一些时间,取决于你的网络带宽。完成后,可以使用以下命令查看本地已有的镜像:

docker images | grep milvus

你应该能看到类似milvusdb/milvus的镜像记录。

2.2 规划持久化存储目录

在Docker中,容器内的数据默认是临时的,容器被删除后数据也会丢失。对于数据库这类有状态服务,数据持久化是必须的。我们需要在宿主机(即你的Ubuntu系统)上创建目录,并将其“映射”到容器内部,这样数据就会保存在宿主机上。

为Milvus创建三个核心目录,分别用于存放配置、数据和日志。选择一个你习惯的位置,例如在/home/your_username/下或系统的/var/lib/目录下。这里以/opt/milvus为例:

sudo mkdir -p /opt/milvus/{conf,db,logs}

这条命令会一次性创建/opt/milvus目录,并在其下创建conf、db、logs三个子目录。

  • conf: 用于存放Milvus服务器的配置文件。你可以在这里放置自定义的server_config.yaml来调整数据库参数。
  • db: Milvus存储向量索引和元数据的核心数据目录。务必确保此目录有足够的磁盘空间。
  • logs: 存放Milvus服务运行过程中产生的日志文件,便于故障排查和监控。

创建完成后,为了方便后续操作,可以将目录所有权更改给当前用户(假设你的用户名是ubuntu):

sudo chown -R ubuntu:ubuntu /opt/milvus

2.3 准备并挂载配置文件(可选但推荐)

Milvus镜像内已经包含了一个默认的配置文件。对于初次体验和简单测试,你可以直接使用默认配置启动。但如果你想深入了解或调整某些参数(如缓存大小、日志级别等),就需要使用自定义配置。

1. 下载默认配置文件 我们可以从Milvus的GitHub仓库获取对应版本的默认配置文件模板。使用wget或curl下载。请注意,配置文件的版本最好与拉取的镜像版本相匹配。例如,对于2.3.x版本:

cd /opt/milvus/conf
wget https://raw.githubusercontent.com/milvus-io/milvus/v2.3.3/configs/milvus.yaml -O server_config.yaml

2. 简要了解关键配置项 用文本编辑器(如nano或vim)打开这个文件看看:

nano /opt/milvus/conf/server_config.yaml

你不需要现在修改所有内容,但可以留意几个常见配置段:

  • common.security: 安全相关设置,如是否启用TLS。
  • etcd / minio / pulsar(或rocksmq): Milvus依赖的底层服务配置。在单机Docker部署中,这些组件通常以standalone模式内嵌运行,配置相对简单。
  • queryNode.gracefulTime: 关闭前的等待时间。
  • log: 日志级别和输出设置。

注意:对于生产环境,强烈建议仔细阅读官方文档并根据硬件资源调整配置。对于本次部署,我们将直接使用下载的默认配置。

2.4 启动Milvus容器

现在是关键一步,我们将通过一个docker run命令启动Milvus服务。这个命令会将之前准备好的目录、端口和配置关联起来。

请将下面命令中的/opt/milvus替换为你实际创建的目录路径(如果不同的话)。

docker run -d \
  --name milvus-standalone \
  -p 19530:19530 \
  -p 9091:9091 \
  -v /opt/milvus/conf:/milvus/configs \
  -v /opt/milvus/db:/var/lib/milvus \
  -v /opt/milvus/logs:/var/lib/milvus/logs \
  milvusdb/milvus:2.3.3-cpu-latest \
  milvus run standalone

让我们逐行拆解这个命令的含义:

参数说明
-d在后台(守护进程)模式运行容器。
--name milvus-standalone为容器指定一个易识别的名称,方便后续管理(如stop, logs命令)。
-p 19530:19530必须。将宿主机的19530端口映射到容器的19530端口。这是Milvus服务端监听客户端gRPC连接的核心端口。
-p 9091:9091推荐。将宿主机的9091端口映射到容器的9091端口。这是Milvus的监控指标端口(通常用于Prometheus拉取数据)。
-v /opt/milvus/conf:/milvus/configs将宿主机的配置目录挂载到容器内的配置路径。如果你在conf目录下放了自定义的server_config.yaml,容器会使用它。
-v /opt/milvus/db:/var/lib/milvus关键持久化。将宿主机的数据目录挂载到容器内Milvus的默认数据存储位置。
-v /opt/milvus/logs:/var/lib/milvus/logs将宿主机的日志目录挂载到容器内的日志路径,方便查看日志。
milvusdb/milvus:2.3.3-cpu-latest指定要运行的镜像名称和标签。
milvus run standalone容器启动后执行的命令,表示以单机模式运行Milvus(包含所有依赖组件)。

执行命令后,Docker会返回一个长长的容器ID。我们可以通过以下命令检查容器是否正在运行:

docker ps

你应该能看到一个名为milvus-standalone的容器,状态(STATUS)显示为“Up”。

2.5 验证服务与查看日志

容器状态为“Up”并不完全代表Milvus服务内部已经就绪。我们需要查看日志来确认启动过程是否成功完成。

使用docker logs命令并添加-f参数可以实时查看(或尾随)日志输出:

docker logs -f milvus-standalone

在启动日志中,你需要关注几个关键的成功信息。当看到类似下面的日志行时,通常意味着服务已成功启动:

[INFO] [session.go:64] ["Session manager started successfully"]
...
[INFO] [impl.go:67] ["Milvus Proxy successfully started!"]

或者,在更新的版本中,可能会看到所有依赖组件(etcd, minio, pulsar/rocksmq)都报告健康状态。等待几十秒到一分钟,直到日志输出趋于平稳,没有明显的ERROR级别报错,然后按Ctrl+C退出日志跟踪。

另一种验证方式是使用netstat检查端口监听情况:

sudo netstat -tlnp | grep 19530

如果看到19530端口处于LISTEN状态,也说明服务端口已经打开。

3. 部署Milvus可视化管理界面(Attu)

通过命令行管理集合(Collection)、插入向量和进行搜索虽然强大,但一个图形化的管理工具能极大提升开发效率和体验。Milvus社区提供了一个名为Attu的开源管理工具,它可以通过Docker快速部署。

3.1 拉取并运行Attu容器

Attu同样提供了Docker镜像。我们拉取最新的稳定版本:

docker pull zilliz/attu:latest

运行Attu容器,并将其端口映射到宿主机的某个端口(例如3000):

docker run -d \
  --name attu \
  -p 3000:3000 \
  -e MILVUS_URL=你的Milvus服务IP:19530 \
  zilliz/attu:latest

这里有一个关键环境变量 MILVUS_URL需要设置。它的值取决于你的网络环境:

  • 如果Attu容器和Milvus容器运行在同一台宿主机上,并且你使用上述命令直接运行,那么可以使用宿主机的内部IP或host.docker.internal(Docker Desktop特性,在Linux原生Docker中可能不支持)或直接使用宿主机对Docker网桥的IP(通常是172.17.0.1)。最保险的方式是使用宿主机的实际局域网IP地址。
    • 例如,你的Ubuntu主机IP是192.168.1.100,那么设置为-e MILVUS_URL=192.168.1.100:19530。
  • 如果你在本地开发(Milvus也在本机),也可以直接使用localhost,但要注意从Attu容器内部能否解析localhost。

假设你的宿主机IP是192.168.1.100,完整的运行命令如下:

docker run -d \
  --name attu \
  -p 3000:3000 \
  -e MILVUS_URL=192.168.1.100:19530 \
  zilliz/attu:latest

3.2 访问与使用Attu

启动后,打开你的浏览器,访问 http://你的宿主机IP:3000。例如 http://192.168.1.100:3000。

首次打开,你会看到一个连接界面。由于我们在环境变量中已经设置了MILVUS_URL,通常Attu会自动尝试连接。如果连接失败,你需要在此界面手动输入Milvus的地址和端口(宿主机IP:19530)。

连接成功后,你将进入Attu的主界面。这里你可以:

  • 创建/管理集合(Collections):定义向量数据的结构,包括维度、索引类型、距离度量方式等。
  • 插入数据:通过上传文件或手动输入的方式,向集合中插入向量和标量数据。
  • 执行向量搜索:输入一个查询向量,设置搜索参数,并即时查看返回的相似结果。
  • 查看系统状态:监控集合中的数据量、索引构建状态等。
  • 执行元数据查询:使用类SQL的布尔表达式进行标量过滤。

Attu的界面直观,将很多复杂的API操作封装成了点击和表单,对于探索数据、调试查询条件特别有帮助。

注意:Attu是一个独立的前端应用,它通过gRPC与Milvus服务端通信。确保防火墙规则允许浏览器访问Attu的端口(3000),并且Attu容器能访问到Milvus的端口(19530)。

4. 进阶配置、管理与故障排查

基础服务跑起来之后,我们还需要了解如何维护它,以及当遇到问题时该如何处理。

4.1 数据持久化与备份的重要性

我们之前通过-v挂载了db目录,这确保了即使milvus-standalone容器被删除或重建,向量数据本身仍然安全地保存在/opt/milvus/db(或你指定的路径)中。这是生产环境部署的黄金法则。

备份策略建议:

  • 定期快照:对于重要的数据,可以定期对/opt/milvus/db目录进行压缩备份。
  • 文件系统级备份:如果运行在云服务器上,可以利用云提供商提供的磁盘快照功能。
  • 逻辑备份(导出):通过Milvus的Python SDK或Go SDK编写脚本,定期将关键集合的元数据和向量数据导出到对象存储(如S3)或其他安全位置。

4.2 常用Docker管理命令

掌握几个简单的Docker命令,能让你轻松管理Milvus和Attu的生命周期。

  • 停止服务:

    docker stop milvus-standalone  # 停止Milvus容器
    docker stop attu               # 停止Attu容器
    
  • 启动服务:

    docker start milvus-standalone
    docker start attu
    
  • 重启服务(修改配置后常用):

    docker restart milvus-standalone
    
  • 进入容器内部(用于调试):

    docker exec -it milvus-standalone /bin/bash
    

    进入后,你可以查看容器内的文件结构、进程状态等。

  • 删除容器(谨慎操作!数据在挂载目录中,所以删除容器不会删除数据):

    docker rm -f milvus-standalone
    

    如果想从头开始,可以删除容器后,用相同的docker run命令(使用相同的挂载目录)重新创建,数据依然存在。

  • 清理无用资源:

    docker system prune -a
    

    此命令会删除所有已停止的容器、未被任何容器使用的网络、悬空的镜像和构建缓存。执行前请确认。

4.3 常见问题与排查思路

1. 容器启动失败,状态为Exited 首先查看详细错误日志:

docker logs milvus-standalone

常见原因:

  • 端口冲突:19530或9091端口已被其他程序占用。使用sudo lsof -i:19530检查,并修改docker run命令中的宿主机端口(如-p 19531:19530)。
  • 挂载目录权限不足:容器进程无法写入挂载的目录。确保/opt/milvus及其子目录对容器内的用户(通常是root)有写权限。可以尝试sudo chmod -R 777 /opt/milvus(宽松权限,仅用于测试)或更精细地设置所有权。
  • 配置文件格式错误:如果你使用了自定义的server_config.yaml,YAML格式错误(如缩进不对、冒号后没空格)会导致启动失败。建议先用在线YAML校验器检查。

2. Attu无法连接到Milvus

  • 检查网络连通性:在Attu容器内,尝试ping你的Milvus宿主机IP。或者,在宿主机上运行telnet 宿主机IP 19530,看端口是否通。
  • 检查环境变量:确认运行Attu时MILVUS_URL设置正确,IP地址是Attu容器能访问到的地址。在Docker默认的bridge网络中,容器间可以通过容器名通信,但需要将它们放在同一个自定义网络中。更简单的方式是使用宿主机的真实IP。
  • 检查Milvus日志:查看Milvus容器日志,确认gRPC服务是否正常启动,是否有连接拒绝的错误。

3. 插入或搜索性能慢

  • 资源限制:默认情况下,Docker容器可以使用宿主机的所有资源。如果机器内存或CPU不足,性能会下降。可以通过docker run的-m和--cpus参数为容器分配资源上限。
  • 索引类型选择:Milvus支持多种索引(如IVF_FLAT, HNSW, SCANN等)。不同的索引在构建速度、搜索速度和内存消耗上有巨大差异。需要根据你的数据规模(向量数量)和查询要求(精度 vs 速度)来选择。Attu在创建集合时可以方便地选择索引。

4. 如何升级Milvus版本 由于数据持久化在宿主机,升级相对安全:

  1. 停止并删除旧版本容器:docker rm -f milvus-standalone。
  2. 拉取新版本镜像:docker pull milvusdb/milvus:新版本-cpu-latest。
  3. 使用完全相同的挂载目录路径和端口映射,运行新版本镜像。
  4. Milvus在启动时会自动检查数据目录的兼容性并进行必要的迁移。务必在升级前备份db目录,并查阅官方发布的升级说明,确认支持从你的旧版本直接升级到目标版本。

整个部署流程走下来,你会发现基于Docker搭建一套现代化的向量数据库服务,并没有想象中那么复杂。关键在于理解“容器化”的思想:将服务、依赖、配置打包成一个可移植的单元,并通过卷挂载实现数据与容器生命周期的解耦。这套方法不仅适用于Milvus,也适用于绝大多数开源数据库和中间件。下次当你需要尝试一个新的数据服务时,不妨先看看Docker Hub上有没有官方镜像,这很可能就是最快的那条上手路径。

更多推荐