🚀 Milvus 实战部署全记录
Milvus 2.5.23 + Attu + 鉴权 + 幂等初始化(Docker Compose)
一、背景说明
在实际工程中部署 Milvus,并不是简单 docker run 就能解决的问题。
本文完整记录了一次 从踩坑到稳定上线 的 Milvus 私有化部署过程。
最终方案选择:
- Milvus v2.5.23(Standalone)
- 开启官方鉴权(RBAC)
- Attu 管理界面
- 幂等的初始化用户方案
- Docker Compose 一键部署
二、为什么选择 Milvus 2.5.23?
放弃 2.6.7 的原因
-
内存要求更高
- 2.6.x 引入 StreamingNode
- 启动时内存占用明显增加
- 8G 内存机器非常吃力
-
MinIO 依赖更激进
- 常搭配
minio/minio:RELEASE.2024-05-28T17-19-04Z - 部分环境下存在 GPU / 指令集兼容问题
- MinIO 起不来 → Milvus 直接失败
- 常搭配
选择 2.5.23 的理由
- 架构成熟
- 资源占用低
- MinIO 兼容性好
- Attu / SDK 稳定
结论:2.5.23 是当前工程部署的"甜点版本"
三、项目目录结构
text
milvus/
├── docker-compose.yml
├── config/
│ └── milvus.yaml
├── init/
│ ├── Dockerfile
│ └── init_user.py
└── volumes/
四、docker-compose.yml
yaml
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.18
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
networks:
- milvus
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
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", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
networks:
- milvus
milvus:
container_name: milvus-standalone
image: milvusdb/milvus:v2.5.23
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
- ${DOCKER_VOLUME_DIRECTORY:-.}/config/milvus.yaml:/milvus/configs/milvus.yaml
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:
- "etcd"
- "minio"
networks:
- milvus
attu:
container_name: milvus-attu
image: zilliz/attu:v2.4
environment:
MILVUS_URL: milvus:19530
MILVUS_USERNAME: root
MILVUS_PASSWORD: Milvus@123
ports:
- "17000:3000"
depends_on:
- "milvus"
networks:
- milvus
init:
build: ./init
container_name: milvus-init
environment:
MILVUS_HOST: milvus
NEW_ROOT_PASSWORD: ******** #设置自己新的密码
APP_USER: ******** #应用账号
APP_PASSWORD: ******** #应用密码
APP_ROLE: admin
networks:
- milvus
depends_on:
- milvus
restart: "no"
networks:
milvus:
五、开启 Milvus 官方鉴权
config/milvus.yaml
yaml
common:
security:
authorizationEnabled: true

开启后:
- 所有客户端必须登录
- Attu 也必须使用账号密码
六、幂等的 Milvus 初始化用户方案
init/Dockerfile
dockerfile
FROM python:3.10-slim-bullseye
RUN pip install --no-cache-dir pymilvus==2.5.16
WORKDIR /app
COPY init-user.py /app/init-user.py
CMD ["python", "/app/init-user.py"]
init/init_user.py
python
import os
import time
from pymilvus import connections, utility, Role
from pymilvus.exceptions import MilvusException
# ---------- 基础配置 ----------
MILVUS_HOST = os.getenv("MILVUS_HOST", "milvus")
MILVUS_PORT = os.getenv("MILVUS_PORT", "19530")
ROOT_USER = "root"
DEFAULT_ROOT_PASSWORD = os.getenv("ROOT_PASSWORD", "Milvus")
NEW_ROOT_PASSWORD = os.getenv("NEW_ROOT_PASSWORD") # 可选
APP_USER = os.getenv("APP_USER", "app_user")
APP_PASSWORD = os.getenv("APP_PASSWORD", "App@123456")
APP_ROLE = os.getenv("APP_ROLE", "admin")
# ---------- 等待 Milvus ----------
print("⏳ Waiting for Milvus to be ready...")
time.sleep(12)
# ---------- 使用默认 root 密码连接 ----------
connections.connect(
alias="default",
host=MILVUS_HOST,
port=MILVUS_PORT,
user=ROOT_USER,
password=DEFAULT_ROOT_PASSWORD
)
# ---------- 修改 root 密码(幂等) ----------
if NEW_ROOT_PASSWORD and NEW_ROOT_PASSWORD != DEFAULT_ROOT_PASSWORD:
try:
utility.update_password(
ROOT_USER,
DEFAULT_ROOT_PASSWORD,
NEW_ROOT_PASSWORD
)
print("✅ Root password updated")
# 重新连接(非常重要)
connections.disconnect("default")
connections.connect(
alias="default",
host=MILVUS_HOST,
port=MILVUS_PORT,
user=ROOT_USER,
password=NEW_ROOT_PASSWORD
)
except MilvusException as e:
if "password is incorrect" in str(e) or "authentication failed" in str(e):
print("ℹ️ Root password already changed, continue")
connections.disconnect("default")
connections.connect(
alias="default",
host=MILVUS_HOST,
port=MILVUS_PORT,
user=ROOT_USER,
password=NEW_ROOT_PASSWORD
)
else:
raise
# ---------- 创建用户 ----------
try:
utility.create_user(APP_USER, APP_PASSWORD)
print(f"✅ User created: {APP_USER}")
except MilvusException as e:
if "already exists" in str(e):
print(f"ℹ️ User already exists: {APP_USER}")
else:
raise
# ---------- 创建角色 ----------
role = Role(APP_ROLE)
try:
role.create()
print(f"✅ Role created: {APP_ROLE}")
except MilvusException as e:
if "already exists" in str(e):
print(f"ℹ️ Role already exists: {APP_ROLE}")
else:
raise
# ---------- 绑定角色 ----------
try:
role.add_user(APP_USER)
print(f"✅ Granted role [{APP_ROLE}] to user [{APP_USER}]")
except MilvusException as e:
if "already" in str(e):
print("ℹ️ Role already granted")
else:
raise
print("🎉 Milvus RBAC initialization finished")
幂等性说明
- 重复执行不会报错
- 适合 CI/CD
- 容器只执行一次即可退出
七、运行与验证
bash
docker compose up -d
成功标志:
-
milvus-init 容器执行后退出,具体的执行日志如下:
csharp#执行脚本 docker logs -f milvus-init
-
Milvus 日志无 ERROR
-
Milvus 的webui管理端,注意这个管理端没有账号与密码,能直接访问

- Attu需要账号密码才能登录,需要自己测试下新的root密码、应用账号与密码

八、踩坑记录
9091 访问不了?
原因:
- Milvus 未完全就绪
- MixCoord 尚未启动完成
解决:
- 耐心等待
- 通过
docker logs -f milvus-standalone查看状态
docker start 看不到日志?
bash
docker logs -f milvus-standalone
没有 /var/lib/milvus/logs 目录?
- 2.5.x 默认日志输出 stdout
- 属于正常现象
有异常需要重新操作
-
看情况,可以选择从新编译init的镜像
csharpdocker-compose build init -
账号信息放在ect里面,根据情况可以删除
bashrm -rf ./volumes/*
九、总结
- Milvus 是工程系统,不是 Demo
- 2.5.23 是当前最稳妥的生产选择
- 初始化用户一定要做成幂等
- 鉴权 + Attu 才是完整方案
一次搭好,后面都省心
完 🎉