生态实践

Docker Compose 一键栈:KWDB + SampleDB + Grafana 本地开发环境五分钟跑起来

原创Caro图懒惰2026-10-28
21
实践目标:用一份 docker-compose.yml 把开源多模时序数据库 KWDB、社区示例项目 SampleDB、生态可视化工具 Grafana 一次性拉起,五分钟内在本地跑通「智能电表」从建库、灌数据到看板展示的完整链路。
本文中所有命令、镜像、端口与 SQL 均来自 KWDB / SampleDB / Grafana 官方文档与仓库,可实际落地。

先说,这套栈都包含什么?

组件组件介绍在本栈中扮演的角色
KWDB开放原子开源基金会孵化及运营的开源分布式多模数据库,基于浪潮KaiwuDB 开源。支持在同一实例同时建立时序库(TSDB)与关系库(RDB)并融合处理多模数据数据底座:同时存「设备/用户/区域/告警规则」关系数据与「电压/电流/功率/能耗」时序数据
SampleDBKWDB 官方示例项目(仓库: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:26257JDBC/ODBC、pg 生态工具、kwbase CLI 均走此端口
KWDB Admin UIhttp://localhost:8080数据库管理界面
Grafanahttp://localhost:3000默认账号 admin / admin
容器网络内 KWDB 地址kwdb:26257Grafana、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 SQLdocker exec -it kwdb ./kwbase sql --insecure --host=127.0.0.1
KWDB 管理界面http://localhost:8080
Grafanahttp://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)

Me