Milvus Docker Compose 部署指南
使用官方 milvusdb/milvus:v3.0.2 镜像通过 Docker Compose 一键部署向量数据库 Milvus,覆盖 Standalone 单机官方编排与手动编排分布式伪集群两种模式,包含数据卷持久化、环境变量注入、健康检查与「建集合→写向量→相似度检索」端到端业务验证
Milvus Docker Compose 部署指南
目标:使用官方
milvusdb/milvus:v3.0.2镜像,通过 Docker Compose 部署向量数据库 Milvus,覆盖官方 Standalone(单机)模式与手动编排的分布式伪集群模式,并完成「建集合 → 写向量 → 相似度检索」的端到端业务验证。本文档面向容器化部署场景,所有操作在具备 Docker Compose 的宿主机上执行,已在 Ubuntu 22.04 + Docker Compose v2 环境实测通过。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04(x86_64/amd64) |
| Docker | 29.x(含 Compose v2 插件) |
| Milvus 镜像 | milvusdb/milvus:v3.0.2 |
| Milvus 版本 | 3.0.2(milvus_build_info{version="3.0.2"}) |
| etcd 镜像 | quay.io/coreos/etcd:v3.5.25 |
| MinIO 镜像 | milvusdb/minio:RELEASE.2024-12-18T13-15-44Z |
| Pulsar 镜像 | apachepulsar/pulsar:2.11.0(伪集群模式) |
| SDK 端口 | 19530(gRPC) |
| WebUI/健康检查端口 | 9091 |
| 数据目录 | ./volumes/{etcd,minio,milvus} |
二、镜像选型说明
Milvus 官方镜像为 milvusdb/milvus,tag 与版本号一一对应,本文使用当前稳定版 3.0.2:
docker pull milvusdb/milvus:v3.0.2
docker pull quay.io/coreos/etcd:v3.5.25
docker pull milvusdb/minio:RELEASE.2024-12-18T13-15-44Z
docker images | grep -E 'milvus|etcd|minio'
⚠️ 注意:Milvus 官方自 v2.2 起不再维护集群模式的官方 docker-compose 文件,官方 compose 仅支持 Standalone(单机)模式;生产级分布式部署官方推荐 Kubernetes(Helm / Milvus Operator)。无 K8s 环境下可使用本文第四章的手动 compose 编排做分布式学习与测试。
三、前置条件
- 宿主机已安装 Docker Engine 与 Docker Compose 插件。
- 具备 root 或 docker 组权限。
- 端口 19530(gRPC)、9091(WebUI)未被占用;伪集群模式额外占用 9000/9001(MinIO)、6650/8080(Pulsar)。
- 至少 8GB+ 可用内存(Milvus 核心 + etcd + MinIO 常驻约 4~6GB)。
docker --version
docker compose version
# Docker version 29.x.x
# Docker Compose version v2.x
四、官方 Standalone 单机部署
4.1 下载官方 compose 文件
mkdir -p /opt/milvus-compose
cd /opt/milvus-compose
wget https://github.com/milvus-io/milvus/releases/download/v3.0.2/milvus-standalone-docker-compose.yaml -O docker-compose.yml
4.2 compose 文件内容
官方 Standalone 文件通过 3 个容器协作组成一个单机 Milvus:milvus-etcd(元数据存储)、milvus-minio(对象存储)、milvus-standalone(Milvus 核心服务),并带一个一次性 milvus-volume-init 数据目录属主迁移服务:
version: '3.5'
x-milvus-image: &milvus-image milvusdb/milvus:v3.0.2
services:
# Remove the .milvus-volume-owner-* marker after restoring files owned by a
# different user so this one-shot migration runs again.
milvus-volume-init:
image: *milvus-image
user: "0:0"
network_mode: none
read_only: true
restart: "no"
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -eu
uid="$$(id -u milvus)"
gid="$$(id -g milvus)"
marker="/var/lib/milvus/.milvus-volume-owner-$${uid}-$${gid}"
if [ ! -e "$${marker}" ]; then
echo "Preparing /var/lib/milvus for $${uid}:$${gid}"
chown -R "$${uid}:$${gid}" /var/lib/milvus
touch "$${marker}"
chown "$${uid}:$${gid}" "$${marker}"
fi
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.25
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 30s
timeout: 20s
retries: 3
minio:
container_name: milvus-minio
image: milvusdb/minio:RELEASE.2024-12-18T13-15-44Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
ports:
- "9001:9001"
- "9000:9000"
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data --console-address ":9001"
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 20s
retries: 3
standalone:
container_name: milvus-standalone
image: *milvus-image
command: ["milvus", "run", "standalone"]
security_opt:
- seccomp:unconfined
environment:
MINIO_REGION: us-east-1
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
start_period: 90s
timeout: 20s
retries: 3
ports:
- "19530:19530"
- "9091:9091"
depends_on:
milvus-volume-init:
condition: service_completed_successfully
etcd:
condition: service_started
minio:
condition: service_started
networks:
default:
name: milvus
4.3 启动并验证
docker compose up -d
# Network milvus Creating ... 三个容器依次创建启动
docker compose ps
# NAME STATUS
# milvus-etcd Up (healthy)
# milvus-minio Up (healthy)
# milvus-standalone Up (healthy)
curl http://127.0.0.1:9091/healthz
# OK
💡 说明:Standalone 模式下 Milvus 各协调器(rootcoord/datacoord/querycoord/indexcoord)以单进程形式合并在
standalone内部运行,默认消息队列为嵌入式 RocksMQ(etcdctl get by-dev/config/mqtype返回rocksmq),无需单独部署 Pulsar/Kafka。
4.4 业务端到端验证(REST API)
Milvus 3.x 提供 HTTP REST API(端口 19530 的 /v2/vectordb/*),可直接用 curl 完成建集合、插入与检索:
# 1. 创建集合
curl -s http://127.0.0.1:19530/v2/vectordb/collections/create -X POST -H 'Content-Type: application/json' -d '{
"collectionName": "book",
"dimension": 8,
"metricType": "L2",
"primaryFieldName": "book_id",
"vectorFieldName": "book_vector",
"fields": [
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true},
{"fieldName": "book_name", "dataType": "VarChar", "maxLength": 256},
{"fieldName": "book_vector", "dataType": "FloatVector", "dim": 8}
]
}'
# {"code":0,"data":{}}
# 2. 插入向量
curl -s http://127.0.0.1:19530/v2/vectordb/entities/insert -X POST -H 'Content-Type: application/json' -d '{
"collectionName": "book",
"data": [
{"book_id": 1, "book_name": "Introduction to Milvus", "book_vector": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]},
{"book_id": 2, "book_name": "Milvus in Action", "book_vector": [0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]},
{"book_id": 3, "book_name": "Vector Database Guide", "book_vector": [0.2, 0.1, 0.5, 0.3, 0.9, 0.4, 0.6, 0.7]},
{"book_id": 4, "book_name": "Advanced Vector Search", "book_vector": [0.9, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]}
]
}'
# {"code":0,"cost":0,"data":{"insertCount":4,"insertIds":[1,2,3,4]}}
# 3. 向量相似度检索(等待数据落盘后执行,返回按 L2 距离升序)
curl -s http://127.0.0.1:19530/v2/vectordb/entities/search -X POST -H 'Content-Type: application/json' -d '{
"collectionName": "book",
"data": [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]],
"annsField": "book_vector",
"limit": 3,
"outputFields": ["book_id", "book_name"]
}'
# {"code":0,"cost":0,"data":[{"book_id":1,"book_name":"Introduction to Milvus","distance":0},
# {"book_id":3,"book_name":"Vector Database Guide","distance":0.28999996},
# {"book_id":4,"book_name":"Advanced Vector Search","distance":0.7099999}],"topks":[3]}
# 4. 查看集合详情
curl -s http://127.0.0.1:19530/v2/vectordb/collections/describe -X POST -H 'Content-Type: application/json' -d '{"collectionName":"book"}'
# {"code":0,"data":{"collectionID":469509374503816523,"collectionName":"book","load":"LoadStateLoaded",...}}
4.5 WebUI 访问
启动完成后可访问 http://127.0.0.1:9091/webui/ 查看 Milvus 实例信息(HTTP 200):
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9091/webui/
# 200
# 版本与构建信息
curl -s http://127.0.0.1:9091/metrics | grep -v '^#' | grep milvus_build_info
# milvus_build_info{built="Fri Sep 18 10:37:46 UTC 2026",git_commit="3c4448a2ae",version="3.0.2"} 1
五、手动编排分布式伪集群(学习/测试)
官方不再提供集群版 compose 文件,以下为按 Milvus 分布式架构手动编排的 compose,适用于理解架构与功能验证,不建议用于生产。核心由 etcd + MinIO + Pulsar + 5 个 Milvus 微服务组成。
💡 说明:Milvus v2.6+ 架构中协调器合并为 mixCoord(rootcoord/datacoord/querycoord/indexcoord 合一),并引入 StreamingNode;indexNode 已并入 DataNode(实测
milvus run indexnode返回Unknown server type = indexnode)。因此集群微服务为:mixcoord、proxy、querynode、datanode、streamingnode。
5.1 准备集群模式配置
集群模式下消息队列必须为独立的 Pulsar(RocksMQ 仅支持单机),需要一份将 mq.type 设为 pulsar 的配置:
mkdir -p /opt/milvus-cluster-config
# 下载官方 milvus.yaml 后修改两处:
# mq.type: default → mq.type: pulsar
# pulsar.address: localhost → pulsar.address: pulsar
# /opt/milvus-cluster-config/milvus.yaml(节选)
mq:
type: pulsar
pulsar:
address: pulsar
port: 6650
5.2 伪集群 compose 文件
version: '3.5'
# Milvus v3.0.2 伪集群编排(学习/测试用途)
# 核心组件:etcd(元数据) + minio(对象存储) + pulsar(消息队列)
# Milvus 微服务:mixcoord(合并协调器) + proxy + querynode + datanode + streamingnode
# 说明:v2.6+ 架构 indexnode 已并入 datanode;官方 docker-compose 仅维护 Standalone 模式,
# 此文件为手动编排的分布式学习环境(伪集群)
x-milvus-image: &milvus-image milvusdb/milvus:v3.0.2
x-milvus-config: &milvus-config
/opt/milvus-cluster-config/milvus.yaml:/milvus/configs/milvus.yaml:ro
x-milvus-env: &milvus-env
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
PULSAR_ADDRESS: pulsar://pulsar:6650
MINIO_REGION: us-east-1
MINIO_BUCKET_NAME: milvus-bucket
ROOT_COORD_ADDRESS: mixcoord:53100
PROXY_ADDRESS: proxy:19530
services:
etcd:
container_name: milvus-cluster-etcd
image: quay.io/coreos/etcd:v3.5.25
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
volumes:
- etcd_data:/etcd
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 30s
timeout: 20s
retries: 3
networks:
- milvus-cluster-net
minio:
container_name: milvus-cluster-minio
image: milvusdb/minio:RELEASE.2024-12-18T13-15-44Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
ports:
- "9001:9001"
- "9000:9000"
volumes:
- minio_data:/minio_data
command: minio server /minio_data --console-address ":9001"
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 20s
retries: 3
networks:
- milvus-cluster-net
pulsar:
container_name: milvus-cluster-pulsar
image: apachepulsar/pulsar:2.11.0
command: bin/pulsar standalone
ports:
- "6650:6650"
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/admin/v2/clusters"]
interval: 30s
timeout: 20s
retries: 3
networks:
- milvus-cluster-net
mixcoord:
container_name: milvus-mixcoord
image: *milvus-image
command: ["milvus", "run", "mixcoord"]
security_opt:
- seccomp:unconfined
environment: *milvus-env
volumes:
- cluster_data:/var/lib/milvus
- *milvus-config
depends_on:
etcd:
condition: service_started
minio:
condition: service_started
pulsar:
condition: service_started
networks:
- milvus-cluster-net
proxy:
container_name: milvus-proxy
image: *milvus-image
command: ["milvus", "run", "proxy"]
security_opt:
- seccomp:unconfined
environment: *milvus-env
ports:
- "19530:19530"
- "9091:9091"
volumes:
- cluster_data:/var/lib/milvus
- *milvus-config
depends_on:
- mixcoord
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
start_period: 90s
timeout: 20s
retries: 3
networks:
- milvus-cluster-net
querynode:
container_name: milvus-querynode
image: *milvus-image
command: ["milvus", "run", "querynode"]
security_opt:
- seccomp:unconfined
environment: *milvus-env
volumes:
- cluster_data:/var/lib/milvus
- *milvus-config
depends_on:
- mixcoord
networks:
- milvus-cluster-net
datanode:
container_name: milvus-datanode
image: *milvus-image
command: ["milvus", "run", "datanode"]
security_opt:
- seccomp:unconfined
environment: *milvus-env
volumes:
- cluster_data:/var/lib/milvus
- *milvus-config
depends_on:
- mixcoord
networks:
- milvus-cluster-net
streamingnode:
container_name: milvus-streamingnode
image: *milvus-image
command: ["milvus", "run", "streamingnode"]
security_opt:
- seccomp:unconfined
environment: *milvus-env
volumes:
- cluster_data:/var/lib/milvus
- *milvus-config
depends_on:
- mixcoord
networks:
- milvus-cluster-net
volumes:
etcd_data:
minio_data:
cluster_data:
networks:
milvus-cluster-net:
name: milvus-cluster-net
5.3 启动与验证
cd /opt/milvus-cluster-compose
docker compose up -d
# 8 个容器依次启动
docker compose ps
# NAME STATUS
# milvus-cluster-etcd Up (healthy)
# milvus-cluster-minio Up (healthy)
# milvus-cluster-pulsar Up (healthy)
# milvus-mixcoord Up
# milvus-proxy Up (healthy)
# milvus-querynode Up
# milvus-datanode Up
# milvus-streamingnode Up
curl http://127.0.0.1:9091/healthz
# OK
# 各组件通过 etcd 完成服务发现注册(实测会话列表)
etcdctl get --prefix by-dev/meta/session --keys-only
# by-dev/meta/session/datacoord
# by-dev/meta/session/datanode-9
# by-dev/meta/session/mixcoord
# by-dev/meta/session/proxy-10
# by-dev/meta/session/querycoord
# by-dev/meta/session/querynode-7
# by-dev/meta/session/querynode-8
# by-dev/meta/session/rootcoord
伪集群业务验证与 Standalone 相同,可直接复用 4.4 节 REST API 命令(同一 19530 端口):
curl -s http://127.0.0.1:19530/v2/vectordb/collections/create -X POST -H 'Content-Type: application/json' \
-d '{"collectionName":"cluster_test","dimension":4,"metricType":"IP","primaryFieldName":"id","vectorFieldName":"vector",
"fields":[{"fieldName":"id","dataType":"Int64","isPrimary":true},{"fieldName":"vector","dataType":"FloatVector","dim":4}]}'
# {"code":0,"data":{}}
curl -s http://127.0.0.1:19530/v2/vectordb/entities/insert -X POST -H 'Content-Type: application/json' \
-d '{"collectionName":"cluster_test","data":[{"id":1,"vector":[1.0,0.0,0.0,0.0]},{"id":2,"vector":[0.9,0.1,0.0,0.0]},{"id":3,"vector":[0.0,1.0,0.0,0.0]}]}'
# {"code":0,"cost":0,"data":{"insertCount":3,"insertIds":[1,2,3]}}
curl -s http://127.0.0.1:19530/v2/vectordb/entities/search -X POST -H 'Content-Type: application/json' \
-d '{"collectionName":"cluster_test","data":[[1.0,0.0,0.0,0.0]],"annsField":"vector","limit":3,"outputFields":["id"]}'
# {"code":0,"cost":0,"data":[{"distance":1,"id":1},{"distance":0.9,"id":2},{"distance":0,"id":3}],"topks":[3]}
六、数据持久化说明
- Standalone 模式:etcd、MinIO、Milvus 数据分别持久化到
./volumes/etcd、./volumes/minio、./volumes/milvus;docker compose down不会删除数据卷,重启后数据仍在。 - 伪集群模式:etcd/MinIO/Milvus 使用命名数据卷
etcd_data/minio_data/cluster_data,同样在 compose 项目内持久化。 - 全部停止并清理(慎用,会删数据):
docker compose down -v。
七、常用环境变量表
| 环境变量 | 说明 | 示例值 |
|---|---|---|
ETCD_ENDPOINTS | etcd 端点列表 | etcd:2379 |
MINIO_ADDRESS | MinIO/S3 服务地址 | minio:9000 |
MINIO_ACCESS_KEY_ID / MINIO_SECRET_ACCESS_KEY | MinIO 访问密钥 | minioadmin |
MINIO_REGION | MinIO 区域 | us-east-1 |
PULSAR_ADDRESS | Pulsar 服务地址(伪集群必填,带 pulsar:// 协议前缀) | pulsar://pulsar:6650 |
DOCKER_VOLUME_DIRECTORY | 官方 compose 的数据卷根目录(默认 .) | /opt/milvus-compose |
八、常用运维命令
# 查看服务状态与日志
docker compose ps
docker compose logs -f standalone
# 进入容器执行命令(如查看配置、运行 milvus CLI)
docker exec -it milvus-standalone sh
# 查看 Milvus 支持的 server type
docker exec milvus-standalone milvus run --help
# [server type] rootcoord proxy querycoord indexnode datanode cdc
# querynode datacoord streamingnode mixcoord standalone mixture
# 停止 / 启动
docker compose stop
docker compose start
# 完全移除(保留数据卷)
docker compose down
九、常见问题(FAQ)
9.1 milvus run indexnode 报 Unknown server type = indexnode
Milvus v2.6+ 将 indexNode 并入 DataNode,indexnode 不再是可独立启动的 server type。集群编排中只需 datanode 一个服务。
9.2 伪集群中 StreamingNode 报 Invalid service URL / service host cannot be empty
原因:PULSAR_ADDRESS 未带协议前缀或地址解析为空。应设置为完整 URL 格式:PULSAR_ADDRESS: pulsar://pulsar:6650。
9.3 创建集合超时(code: 10001, message: request timeout)
组件刚启动尚未完成服务发现时出现。等待 1~2 分钟,确认 docker compose ps 全部 Up (healthy) 后重试。
9.4 搜索报 collection not loaded 或 index not found
Milvus 3.x 检索前必须:先给向量字段建索引,再 load_collection 将集合加载进内存。REST API 流程中先 create_index(或等待 AUTOINDEX 构建完成),再用 pymilvus 的 load_collection()。
十、参考链接
- Milvus 官方下载页:https://zilliz.com/milvus-downloads
- v3.0.2 Release:https://github.com/milvus-io/milvus/releases/tag/v3.0.2
- Milvus 文档(安装总览):https://milvus.io/docs/install-overview.md
- pymilvus API 参考:https://milvus.io/api-reference/pymilvus/v3.0.x/About.md