不能直接用root运行Prometheus,因其会读取配置、监听端口、写入TSDB目录,一旦配置被恶意利用将导致系统级风险;正确做法是创建专用用户(如prometheus),严格授权配置文件和data目录,并在systemd服务中显式指定--storage.tsdb.path等关键参数。

直接上生产环境,别用 root 启动 Prometheus;二进制手动安装适合验证,systemd 服务化才是长期运行的正确姿势;Docker 方式看似简单,但路径挂载、时区、--storage.tsdb.path 权限问题频发,新手容易卡在数据无法持久化这一步。
为什么不能直接用 root 运行 prometheus
Prometheus 官方明确不建议以 root 身份运行服务进程。它会读取配置、监听端口、写入 TSDB 数据目录,一旦配置被注入恶意重定向或路径遍历,风险直接升级为系统级。实际部署中常见错误现象包括:
- 启动后
curl http://localhost:9090/metrics返回 404 或空响应 —— 很可能是prometheus.yml路径写错,或文件权限不允许prometheus用户读取 -
level=error ts=2026-05-22T21:28:12.123Z caller=main.go:464 msg="Error loading config" err="open /usr/local/prometheus/prometheus.yml: permission denied"—— systemd 服务里指定了User=prometheus,但chown漏掉了配置文件本身 - 日志里反复出现
tsdb: open block: permission denied——/usr/local/prometheus/data目录所有者是root,而服务以prometheus用户运行
正确做法是:创建专用用户,且只赋予最小必要权限:
sudo useradd --no-create-home --shell /bin/false prometheus sudo chown -R prometheus:prometheus /usr/local/prometheus sudo chown prometheus:prometheus /usr/local/prometheus/prometheus.yml
systemd 服务配置里必须显式指定 --storage.tsdb.path
从 v2.39 开始,Prometheus 默认将 TSDB 数据写入当前工作目录下的 data/,但 systemd 服务的 WorkingDirectory 不一定可控。如果不显式传参,服务可能把数据写进 /run/systemd/ 或 /tmp 下的临时路径,重启即丢。
常见错误配置(缺参数):
[Service] ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml
应改为(含路径、监听地址、数据目录三要素):
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
[Service] User=prometheus Group=prometheus ExecStart=/usr/local/prometheus/prometheus \ --config.file=/usr/local/prometheus/prometheus.yml \ --storage.tsdb.path=/usr/local/prometheus/data \ --web.listen-address=:9090
注意:--storage.tsdb.path 必须是绝对路径,且该目录需提前创建并授权;若使用相对路径,systemd 会按 unit 文件所在位置解析,极易出错。
Docker 启动时 volumes 挂载必须映射 prometheus.yml 和 data 目录
Docker 容器默认是无状态的,不挂载 data 目录等于每次 docker-compose up -d 都重置整个时间序列数据库。更隐蔽的问题是:容器内 prometheus 进程以 uid=65534(nobody) 运行,宿主机挂载目录若属主不是该 uid,TSDB 初始化会失败,日志仅显示 tsdb: open head block: permission denied,无其他线索。
安全挂载方式(推荐):
- 宿主机上先创建数据目录并设宽松权限:
sudo mkdir -p /opt/prometheus/data && sudo chmod 777 /opt/prometheus/data -
docker-compose.yml中明确挂载两处:
volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - /opt/prometheus/data:/prometheus
其中 :ro 表示配置只读,防容器内误改;/prometheus 是镜像内默认 TSDB 路径,无需额外加 --storage.tsdb.path 参数。
验证是否真跑起来了,别只看 curl :9090
能打开 Web 页面 ≠ Prometheus 正常采集指标。关键要看两个地方:
- 访问
http://IP:9090/targets:确认State列全为UP,且Last Scrape时间距现在不超过scrape_interval(默认 15s) - 执行 PromQL 查询:
count by (job) ({__name__=~".+"})—— 应返回至少一个 job(比如prometheus),否则说明抓取完全没生效 - 如果 targets 显示
context deadline exceeded,大概率是targets地址填了localhost:容器内 localhost ≠ 宿主机 localhost,得换host.docker.internal(Docker Desktop)或宿主机真实 IP
最容易被忽略的一点:Node Exporter 必须单独部署并确保 :9100/metrics 可访问,否则即使 Prometheus 自身 target 是 UP 的,你也看不到任何主机指标 —— 因为默认配置里根本没配它。

















