实践目标:用一份 docker-compose.yml 把开源多模时序数据库 KWDB、社区示例项目 SampleDB、生态可视化工具 Grafana 一次性拉起,五分钟内在本地跑通「智能电表」从建库、灌数据到看板展示的完整链路。
本文中所有命令、镜像、端口与 SQL 均来自 KWDB / SampleDB / Grafana 官方文档与仓库,可实际落地。
先说,这套栈都包含什么?
| 组件 | 组件介绍 | 在本栈中扮演的角色 |
| KWDB | 开放原子开源基金会孵化及运营的开源分布式多模数据库,基于浪潮KaiwuDB 开源。支持在同一实例同时建立时序库(TSDB)与关系库(RDB)并融合处理多模数据 | 数据底座:同时存「设备/用户/区域/告警规则」关系数据与「电压/电流/功率/能耗」时序数据 |
| SampleDB | KWDB 官方示例项目(仓库:gitee.com/kwdb/sampledb / github.com/KWDB/SampleDB),内置智能电表、跨模查询、窗口函数、聚合函数等可运行示例 | 数据源:装载「智能电表」示例的关系库 rdb(4 张表)与时序库 tsdb(1 张时序表) |
| Grafana | 主流可视化与监控看板 | 可视化:用内置 PostgreSQL 数据源直连 KWDB(KWDB 兼容PostgreSQL 线协议),无需额外插件 |
为什么能实现一键: KWDB 官方 Docker 镜像 kwdb/kwdb 内置 kwbase CLI 并可直接启动单节点;SampleDB 官方脚本通过 kwbase sql 与 import database csv data ("nodelocal://1/…") 完成建库灌数据;Grafana 通过 provisioning 目录自动注册数据源与看板。三者用Compose 串成一条流水线即可。
前置条件
· Docker ≥ 20.10,docker compose ≥ 2.x(docker compose version 确认)。
· 能拉取 kwdb/kwdb 与 grafana/grafana 镜像(国内环境可为 docker 配置镜像加速)。
· 本地空闲端口:26257(KWDB SQL)、8080(KWDB Admin UI)、3000(Grafana)。
端口和调用路径
| 入口 | 地址 | 说明 |
| KWDB SQL(PG协议) | localhost:26257 | JDBC/ODBC、pg 生态工具、kwbase CLI 均走此端口 |
| KWDB Admin UI | http://localhost:8080 | 数据库管理界面 |
| Grafana | http://localhost:3000 | 默认账号 admin / admin |
| 容器网络内 KWDB 地址 | kwdb:26257 | Grafana、SampleDB 装载任务通过该主机名访问 |
1. 第一步:准备代码
mkdir kwdb-stack && cd kwdb-stack
# clone SampleDB(后续装载任务会挂载 smart-meter 示例目录)
git clone https://gitee.com/kwdb/sampledb.git
# 若 gitee 不可达,可用 GitHub 镜像:https://github.com/KWDB/SampleDB.git
clone 完成后,确认 SampleDB/smart-meter/ 目录存在,且 extern/ 下有 rdb.tar.gz 与 tsdb.tar.gz 两个示例数据包(官方导入机制依赖它们)。
2. 第二步:编写 docker-compose.yml
在 kwdb-stack/ 下创建 docker-compose.yml:
version: "3.8"
services:
kwdb:
image: kwdb/kwdb
container_name: kwdb
privileged: true # 官方 docker run 即要求 privileged
ipc: shareable # 官方 docker run 即要求 --ipc shareable
working_dir: /kaiwudb/bin
ports:
- "26257:26257" # SQL / PostgreSQL 线协议端口
- "8080:8080" # Admin UI / HTTP 端口
volumes:
- kwdb-store:/kaiwudb/deploy/kaiwudb-container # 数据目录(也是 nodelocal 导入目录的根)
command: >
./kwbase start-single-node
--insecure
--listen-addr=0.0.0.0:26257
--http-addr=0.0.0.0:8080
--store=/kaiwudb/deploy/kaiwudb-container
healthcheck:
test: ["CMD", "/kaiwudb/bin/kwbase", "sql", "--insecure", "--host=127.0.0.1", "--execute=SELECT 1"]
interval: 5s
timeout: 5s
retries: 30
start_period: 20s
restart: unless-stopped
sampledb:
image: kwdb/kwdb # 复用同镜像,内部自带 kwbase CLI
container_name: kwdb-sampledb
depends_on:
kwdb:
condition: service_healthy # 等 kwdb 就绪后再装载
working_dir: /opt/sampledb
volumes:
- ./SampleDB/smart-meter:/opt/sampledb:ro # 挂载已 clone 的示例目录
- ./scripts:/opt/scripts:ro # 挂载装载脚本
- kwdb-store:/kaiwudb/deploy/kaiwudb-container # 与 kwdb 共享数据卷,用于写 nodelocal 导入目录
entrypoint: ["/bin/bash", "/opt/scripts/load-sampledb.sh"]
restart: "no" # 一次性任务,跑完即退出
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning:ro # 数据源与看板自动预置
depends_on:
- kwdb
restart: unless-stopped
volumes:
kwdb-store:
参数说明均来自 KWDB 官方 Docker 快速开始:docker run -d --privileged --name kwdb -p 26257:26257 -p 8080:8080 ... kwdb/kwdb ./kwbase start-single-node --insecure --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 --store=/kaiwudb/deploy/kaiwudb-container。Compose 只是把它参数化、加健康检查并编排了依赖。
参数说明均来自 KWDB 官方 Docker 快速开始:docker run -d --privileged --name kwdb -p 26257:26257 -p 8080:8080 ... kwdb/kwdb ./kwbase start-single-node --insecure --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 --store=/kaiwudb/deploy/kaiwudb-container。
Compose 只是把它参数化、加健康检查并编排了依赖。
3. 第三步:SampleDB 装载脚本
SampleDB 不是常驻服务,而是一套可运行脚本。官方容器模式的本质是:把示例数据包放进 KWDB 节点本地导入目录,再用kwbase sql 执行 import database csv data ("nodelocal://1/<库名>") 完成建库灌数据。
Compose 里我们用「一次性装载容器 + 共享数据卷」复现同一机制。
创建 scripts/load-sampledb.sh:
#!/bin/bash
# SampleDB 智能电表示例数据装载脚本(一次性任务)
set -euo pipefail
STORE="/kaiwudb/deploy/kaiwudb-container" # 与 kwdb 共享的数据目录
SRC="/opt/sampledb"
KWBASE="/kaiwudb/bin/kwbase"
ADDR="kwdb:26257"
log() { echo "[sampledb] $*"; }
# 0) 准备节点本地 extern 导入目录
mkdir -p "$STORE/extern"
# 1) 用官方 create_load.sql 导入 rdb / tsdb(先删库再导入,可重复执行)
if [ -f "$SRC/create_load.sql" ] && [ -f "$SRC/extern/rdb.tar.gz" ] && [ -f "$SRC/extern/tsdb.tar.gz" ]; then
log "解压 rdb / tsdb 示例数据包到 extern/"
tar -xzf "$SRC/extern/rdb.tar.gz" -C "$STORE/extern/"
tar -xzf "$SRC/extern/tsdb.tar.gz" -C "$STORE/extern/"
log "执行 create_load.sql(导入关系库 rdb、时序库 tsdb)"
"$KWBASE" sql --insecure --host="$ADDR" < "$SRC/create_load.sql"
else
log "警告:未找到 create_load.sql 或 extern 数据包,跳过官方导入。请确认 SampleDB 已正确 clone。"
fi
# 2) 追加生成 10000 条“近期”模拟时序数据(M1~M100,近约 69 天)
# 保证 Grafana 默认时间范围立即有数据可看
"$KWBASE" sql --insecure --host="$ADDR" --execute="
INSERT INTO tsdb.meter_data(ts, voltage, current, power, energy, meter_id)
SELECT
NOW()-(s*10)::int * INTERVAL '1 minute',
220.0 + (s%10)::float,
5.0 + (s%15)::float * 0.1,
1000.0 + (s%20)::float * 50,
5000.0 + s::float * 10,
'M' || ((s%100)+1)::text
FROM generate_series(1, 10000) AS s;
"
# 3) 验证
log "关系库 rdb 表清单:"; "$KWBASE" sql --insecure --host="$ADDR" --execute="SHOW TABLES FROM rdb;"
log "时序库 tsdb 表清单:"; "$KWBASE" sql --insecure --host="$ADDR" --execute="SHOW TABLES FROM tsdb;"
log "meter_data 行数:"; "$KWBASE" sql --insecure --host="$ADDR" --execute="SELECT COUNT(*) AS rows FROM tsdb.meter_data;"
log "装载完成。打开 http://localhost:3000 (admin/admin) 查看看板。"
说明:nodelocal://1/<库名> 指向 KWDB 节点本地存储目录下的 extern/<库名>,这正是 SampleDB prepare_data.sh / 容器模式 docker cp的处理方式,这里改由共享卷写入。
4. 第四步:Grafana 数据源与看板预置
Grafana 用 provisioning 目录免手工配置。创建 grafana/provisioning/datasources/kwdb.yml:
apiVersion: 1
datasources:
- name: KWDB
uid: kwdb
type: postgres # KWDB 兼容 PostgreSQL 线协议,用内置 PG 数据源即可
access: proxy
url: kwdb:26257 # 容器网络内主机名:SQL端口
user: root # insecure 模式默认超级用户 root,密码为空
secureJsonData:
password: ""
jsonData:
database: tsdb # 默认库设为时序库 tsdb
sslmode: disable
isDefault: true
创建 grafana/provisioning/dashboards/dashboards.yml:
apiVersion: 1
providers:
- name: KWDB Dashboards
orgId: 1
folder: "KWDB"
type: file
disableDeletion: false
updateIntervalSeconds: 10
options:
path: /etc/grafana/provisioning/dashboards
创建 grafana/provisioning/dashboards/kwdb-smart-meter.json(一个时序面板 + 一个跨模查询表格面板,uid: kwdb-smart-meter):
{
"uid": "kwdb-smart-meter",
"title": "KWDB 智能电表",
"refresh": "10s",
"time": { "from": "now-6h", "to": "now" },
"timezone": "browser",
"templating": {
"list": [
{
"name": "meter",
"type": "query",
"datasource": { "type": "postgres", "uid": "kwdb" },
"query": "SELECT DISTINCT meter_id FROM tsdb.meter_data ORDER BY meter_id",
"refresh": 1,
"current": { "text": "M1", "value": "M1" }
}
]
},
"panels": [
{
"type": "timeseries",
"title": "电表 $meter 电压 / 电流 / 功率(实时趋势)",
"datasource": { "type": "postgres", "uid": "kwdb" },
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
"targets": [
{
"refId": "A",
"format": "time_series",
"rawSql": "SELECT\n $__time(ts) AS \"time\",\n voltage,\n current,\n power,\n meter_id AS metric\nFROM tsdb.meter_data\nWHERE $__timeFilter(ts) AND meter_id = '$meter'\nORDER BY ts"
}
]
},
{
"type": "table",
"title": "区域用电量 TOP 10(跨模查询:时序表 JOIN 关系表)",
"datasource": { "type": "postgres", "uid": "kwdb" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
"targets": [
{
"refId": "B",
"format": "table",
"rawSql": "SELECT\n a.area_name,\n ROUND(SUM(md.energy)) AS total_energy\nFROM tsdb.meter_data md\nJOIN rdb.meter_info mi ON md.meter_id = mi.meter_id\nJOIN rdb.area_info a ON mi.area_id = a.area_id\nGROUP BY a.area_name\nORDER BY total_energy DESC\nLIMIT 10"
}
]
}
]
}
---
5. 第五步:一键启动
cd kwdb-stack
docker compose up -d
观察装载任务进度:
docker compose ps # kwdb/grafana 为 Up,sampledb 应已 Exited(0)
docker compose logs -f sampledb # 查看建库、灌数据、生成时序数据的日志
确认装载成功后,用 kwbase 进入 KWDB 验证:
docker exec -it kwdb ./kwbase sql --insecure --host=127.0.0.1
# 库内验证
SHOW TABLES FROM rdb; -- alarm_rules / area_info / meter_info / user_info
SHOW TABLES FROM tsdb; -- meter_data (TIME SERIES TABLE)
SELECT COUNT(*) FROM tsdb.meter_data; -- 10100(导入) + 10000(生成)
6. 第六步:在 Grafana 里看数据
打开 http://localhost:3000(账号 admin/admin),左侧即出现「KWDB」数据源与「KWDB 智能电表」看板。
· 时序面板:电表电压 / 电流 / 功率实时趋势(顶部下拉切换电表 M1~M100)。
· 表格面板:区域用电量 TOP10 —— 用一条 SQL 同时 JOIN 时序表 tsdb.meter_data 与关系表 rdb.meter_info、rdb.area_info,直观体验 KWDB 的跨模查询能力。
如果需要在 SQL 编辑器里手动执行,可直接使用 kwdb-stack/sample-queries.sql 中的语句(下方表格中已列出)。
调用路径
| 场景 | 命令 / 地址 |
| 拉起整栈 | docker compose up -d |
| 停栈 | docker compose down(保留数据卷加 -v 可清空) |
| 进入 KWDB SQL | docker exec -it kwdb ./kwbase sql --insecure --host=127.0.0.1 |
| KWDB 管理界面 | http://localhost:8080 |
| Grafana | http://localhost:3000(admin/admin) |
| Java/ODBC 连接串 | jdbc:postgresql://localhost:26257/tsdb,user=root,password 空 |
| 装载数据(若 sampledb 任务未跑) | cd SampleDB/smart-meter && bash smart_meter_test.sh --container kwdb |
可能出现的问题及解法
1. `docker compose up` 后 `sampledb` 容器报错退出
先看 docker compose logs sampledb。最常见原因是 ./SampleDB/smart-meter/extern 下缺少 rdb.tar.gz / tsdb.tar.gz(部分 clone 未包含大文件)。补齐后再 docker compose up sampledb(或 docker compose up -d 重跑)即可。
2. Grafana 数据源显示连接失败
确认 KWDB 已健康(docker compose ps),且数据源 URL 为容器网络主机名 kwdb:26257。本地用其他客户端先测:docker exec -it kwdb ./kwbase sql --insecure --host=127.0.0.1。
3. 看板没有数据
Grafana 默认时间范围为最近 6 小时,而 load-sampledb.sh 已生成近 69 天的数据,理论上应有曲线。若仍为空,检查面板顶部时间范围,或在 sample-queries.sql 中直接执行第 5 条 SQL 验证。
4. 想清空重来
docker compose down -v 删除数据卷,重新 up。
5. 个别 PG 方言差异
KWDB 兼容 PG 协议,基础查询与 Grafana 宏($__timeFilter 等)可直接使用;若用到高级方言特性,需要按 KWDB 文档做微调。
彩蛋:一行体验 Smart Meter Web
若只想快速看效果,SampleDB 还提供了一个 Web 演示镜像(内部已打包 KWDB + 前后端 + 全量模拟数据,与上面的共享栈相互独立):
docker run -d --name smart-meter -p 3001:3001 kwdb/smart-meter:latest
# 访问 http://localhost:3001

评论(0)