ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Windows下基于Docker与WSL2部署ThingsBoard物联网平台及网关全攻略

Windows下基于Docker与WSL2部署ThingsBoard物联网平台及网关全攻略 1. 项目概述与核心价值最近在折腾物联网平台想把家里的一些传感器数据统一管起来顺带测试一些设备接入协议。ThingsBoard这个开源物联网平台在圈子里口碑一直不错功能全社区也活跃。但说实话直接在生产环境部署它的全套服务对资源要求不低而且环境配置也挺折腾。对于我这种想快速搭建一个测试或开发环境又不想把本地Windows机器搞得一团糟的人来说Docker无疑是最佳选择。它能把应用和依赖打包成一个独立的容器和环境隔离开装和卸都干净利落。这个“WindowsDockerThingsBoardThingsBoard Gateway安装”的方案核心目标就是让你在Windows电脑上用最省事的方式跑起一个功能完整的ThingsBoard物联网平台并且把它的网关服务也一并装上。ThingsBoard Gateway是个关键组件它相当于一个协议翻译官能把像MQTT、Modbus、OPC-UA这些设备常用的“方言”转换成ThingsBoard平台能听懂的“普通话”。这样一来你手头各种各样的设备无论是通过Wi-Fi、4G还是串口连接的就都能把数据上报到这个平台了。整个过程下来你会发现这不仅仅是“安装”两个字那么简单。它涉及到Windows环境下Docker的选型与配置、ThingsBoard核心服务的容器化部署、数据库的初始化、网关服务的配置与连接以及最后如何验证整个系统是否跑通。我会把每一步的原理、为什么这么选、以及我踩过的坑都详细道来目标是让你看完后能独立复现一个可用的环境并且理解背后的逻辑而不仅仅是照抄命令。2. 环境准备Windows上的Docker选择与配置在Windows上玩Docker首先得选对“跑道”。主要有两个选择Docker Desktop 和 Docker Engine配合WSL2。我强烈推荐后者理由很简单性能更好、资源占用更可控、更贴近Linux原生环境而且对于ThingsBoard这种可能涉及多个容器和网络通信的场景稳定性更高。2.1 启用WSL2并安装Linux发行版WSL2Windows Subsystem for Linux 2是微软官方的Linux子系统它提供了一个完整的Linux内核让Docker容器能直接跑在上面性能损耗极小。第一步以管理员身份打开Windows PowerShell执行下面的命令来启用WSL和虚拟机平台功能。这个操作需要重启电脑。# 启用WSL功能 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart # 启用虚拟机平台功能这是WSL2的基础 dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart执行完后重启你的电脑。第二步重启后继续在PowerShell中设置WSL2为默认版本。# 将WSL的默认版本设置为2 wsl --set-default-version 2第三步去Microsoft Store应用商店搜索并安装一个Linux发行版比如“Ubuntu”或“Debian”。我习惯用Ubuntu因为它社区大遇到问题好找答案。安装完成后从开始菜单启动它它会完成初始的用户名和密码设置。注意安装Linux发行版时设置的用户名和密码是你在这个子系统里的凭证请务必记住。这个账户默认拥有sudo权限。2.2 安装Docker Engine现在我们进入安装好的Ubuntu子系统环境。接下来的操作都在这个Linux命令行里进行。首先更新软件包列表然后安装Docker所需的一些工具和依赖。# 更新apt包索引 sudo apt-get update # 安装一些必要的工具用于通过HTTPS使用仓库 sudo apt-get install -y ca-certificates curl gnupg lsb-release接着添加Docker官方的GPG密钥和软件仓库。# 创建目录存放密钥环 sudo mkdir -p /etc/apt/keyrings # 下载并添加Docker的官方GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加Docker的APT仓库 echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null再次更新包列表并安装Docker Engine、命令行工具以及容器运行时。sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin安装完成后将当前用户添加到docker用户组这样以后运行docker命令就不需要每次都加sudo了。sudo usermod -aG docker $USER重要执行完上面的命令后你需要完全关闭当前的Ubuntu终端窗口然后重新打开一个新的。这样用户组的变更才会生效。重新打开后运行docker version如果能看到Client和Server的版本信息说明安装成功。2.3 配置Docker守护进程与镜像加速默认安装的Docker服务会随系统启动。我们可以检查一下它的状态。# 检查Docker服务状态 sudo systemctl status docker # 如果没启动可以用下面命令启动并设置开机自启 sudo systemctl start docker sudo systemctl enable docker在国内访问Docker Hub拉取镜像可能会很慢我们需要配置一个镜像加速器。这里以阿里云镜像加速为例你需要有一个阿里云账号在容器镜像服务里获取专属加速器地址。编辑Docker的守护进程配置文件。sudo nano /etc/docker/daemon.json如果文件是空的就填入以下内容将https://xxxx.mirror.aliyuncs.com替换成你自己的加速器地址。如果文件已有内容就在registry-mirrors这个数组里添加你的加速器地址。{ registry-mirrors: [https://xxxx.mirror.aliyuncs.com] }保存退出后重启Docker服务使配置生效。sudo systemctl daemon-reload sudo systemctl restart docker验证加速器是否生效可以运行docker info在输出结果中查找Registry Mirrors看看是否包含了你配置的地址。至此一个高性能、易于管理的Docker环境就在你的Windows上准备就绪了。这个基于WSL2的方案比Docker Desktop少了图形界面的开销但换来的是更纯粹、更高效的命令行体验对于后续的部署操作来说其实更加方便。3. ThingsBoard核心服务部署详解ThingsBoard官方提供了非常完善的Docker Compose部署脚本这让我们部署变得异常简单。Docker Compose可以通过一个YAML文件定义和运行多个容器正好适合ThingsBoard这种由多个服务应用、数据库、缓存等组成的系统。3.1 获取与解析官方部署脚本首先我们在WSL2的Ubuntu子系统里找一个合适的工作目录比如~/thingsboard。mkdir -p ~/thingsboard cd ~/thingsboard然后直接从ThingsBoard的GitHub仓库拉取最新的Docker Compose部署文件。这里我们选择包含PostgreSQL数据库和Redis缓存的版本这是最常用、也最稳定的组合。# 下载docker-compose.yml文件 wget https://raw.githubusercontent.com/thingsboard/thingsboard/master/docker-compose/docker-compose.postgres.yml -O docker-compose.yml # 下载环境变量配置文件示例 wget https://raw.githubusercontent.com/thingsboard/thingsboard/master/docker-compose/docker-compose.postgres.env -O .env现在让我们打开docker-compose.yml文件看一眼结构理解一下我们要启动哪些服务。cat docker-compose.yml | head -50你会看到它主要定义了三个服务tb-postgres: 这是PostgreSQL数据库容器ThingsBoard的所有结构化数据设备档案、资产关系、遥测数据、用户信息等都存在这里。tb-redis: 这是Redis缓存容器。ThingsBoard用它来缓存会话信息、设备连接状态、规则引擎的元数据等能极大提升平台响应速度。tb: 这就是ThingsBoard应用本身一个基于Java Spring Boot的Web服务。它依赖前面的数据库和缓存。这个编排文件还定义了容器之间的网络确保它们能互相通信并且将数据库的数据卷volume映射到宿主机这样即使容器删除数据也不会丢失。3.2 启动服务与初始化数据库在启动之前我们可以按需修改.env文件。比如默认的PostgreSQL密码是“postgres”你可以改成一个更复杂的。但如果是本地测试用默认的也行方便记忆。nano .env找到POSTGRES_PASSWORDpostgres这一行可以修改等号后面的值。保存退出。现在使用Docker Compose命令启动所有服务。-d参数表示在后台运行。docker-compose up -d第一次运行这个命令会花费一些时间因为它需要从Docker Hub拉取三个镜像ThingsBoard, PostgreSQL, Redis。镜像拉取完成后会自动创建并启动容器。启动完成后用下面的命令查看容器状态。docker-compose ps如果看到三个服务的状态都是“Up”就表示启动成功了。但先别急ThingsBoard服务第一次启动时会自动执行数据库初始化脚本创建表、插入默认数据等。这个过程需要一点时间特别是初始化规则引擎组件时。我们可以通过查看ThingsBoard容器的日志来观察初始化进度。# 查看tb容器的实时日志 docker-compose logs -f tb当你看到日志中出现类似“Started ThingsBoard Server Application in XX seconds”的字样时说明应用已经启动完毕数据库也初始化好了。3.3 访问验证与默认登录ThingsBoard默认的服务端口是8080。由于我们的Docker运行在WSL2的Linux子系统中这个端口已经自动映射到了Windows主机上。你可以在Windows的浏览器中直接访问http://localhost:8080如果一切正常你将看到ThingsBoard的登录页面。系统默认提供了一个超级管理员账户用户名: sysadminthingsboard.org密码: sysadmin重要安全提示首次登录后系统会强制要求你修改这个默认密码。请务必修改为一个强密码并妥善保管。这个账户拥有系统的最高权限。登录成功后你就进入了ThingsBoard的主仪表盘。到这里ThingsBoard的核心平台就已经在你的Windows上通过Docker成功运行起来了。你可以先花点时间熟悉一下界面设备管理、资产管理、仪表盘、规则链等等。接下来我们要把网关服务接进来。4. ThingsBoard Gateway服务部署与配置ThingsBoard Gateway是一个独立运行的服务它的职责是作为ThingsBoard平台与外部设备之间的桥梁。它支持多种协议我们这里以最常用的MQTT为例进行配置和连接。4.1 拉取网关镜像与创建配置文件ThingsBoard Gateway也有官方的Docker镜像。我们不需要再写一个复杂的docker-compose.yml直接运行一个容器并通过挂载卷的方式提供配置即可。首先拉取最新的网关镜像。docker pull thingsboard/tb-gateway接下来我们需要为网关准备配置文件。在宿主机WSL2的Ubuntu上创建一个目录来存放配置。mkdir -p ~/tb-gateway/config cd ~/tb-gateway/config网关的核心配置文件是tb_gateway.yaml。我们创建一个最基本的版本。nano tb_gateway.yaml将以下内容粘贴进去。这里做了最关键的两项配置连接ThingsBoard通过host和port指定我们刚刚部署的ThingsBoard服务的地址。因为网关容器和ThingsBoard容器在同一个Docker默认网络中我们可以直接用服务名tb作为主机名。端口是8080。启用MQTT服务在connectors部分启用了MQTT连接器并让它监听1883端口。这样外部的MQTT设备比如ESP8266、模拟客户端就可以连接到这个网关的1883端口上报数据了。thingsboard: host: tb port: 8080 remoteShell: false remoteConfiguration: false security: accessToken: YOUR_GATEWAY_ACCESS_TOKEN storage: type: memory read_records_count: 100 max_records_count: 100000 connectors: - type: mqtt name: MQTT Broker Connector configuration: mqtt.json保存并退出。注意这里的accessToken我们暂时写了一个占位符YOUR_GATEWAY_ACCESS_TOKEN。这个Token需要我们在ThingsBoard平台上创建一个网关设备来获取。4.2 在ThingsBoard中创建设备并获取令牌回到ThingsBoard的Web界面http://localhost:8080。在左侧导航栏进入“设备”-“设备组”-“所有”。点击页面右上角的“”号选择“创建设备”。在“创建设备”对话框中名称填写一个易于识别的名字例如My Docker Gateway。设备类型填写gateway。这个类型标签有助于后续管理。是否网关务必勾选这个复选框。只有勾选了这个设备才能被网关服务连接。点击“添加”按钮创建设备。在设备列表中找到你刚创建的网关设备点击它的名字进入详情页。在详情页点击右上角的“复制访问令牌”按钮。这个长字符串就是你的网关凭证。4.3 启动网关容器并连接现在我们有了访问令牌需要更新网关的配置文件。同时我们还需要一个MQTT连接器的详细配置文件。cd ~/tb-gateway/config # 编辑主配置替换访问令牌 nano tb_gateway.yaml将security:下的accessToken:后面的值替换为你刚刚复制的真实令牌。务必去掉引号内的空格。然后保存。接下来创建MQTT连接器的配置文件。nano mqtt.json输入以下基础配置。这个配置告诉网关的MQTT连接器监听1883端口并且将任何向/sensor/data主题发布消息的客户端都视为一个独立的设备其设备名取自消息中的deviceName字段。{ broker: { name:Default Local Broker, host:0.0.0.0, port:1883, security: { type: anonymous } }, mapping: [ { topicFilter: /sensor/data, converter: { type: json, deviceNameJsonExpression: ${deviceName}, deviceTypeJsonExpression: ${deviceType}, timeout: 60000, attributes: [ ], timeseries: [ { type: double, key: temperature, value: ${temperature} }, { type: double, key: humidity, value: ${humidity} } ] } } ] }保存退出。现在万事俱备可以启动网关容器了。运行以下命令docker run -d --name tb-gateway \ --restart always \ --network thingsboard_default \ -p 1883:1883 \ -v ~/tb-gateway/config:/config \ thingsboard/tb-gateway逐条解释一下这个命令-d: 后台运行。--name tb-gateway: 给容器起个名字。--restart always: 容器退出时总是重启保证服务高可用。--network thingsboard_default: 这是关键让网关容器加入到ThingsBoard核心服务所在的Docker网络中。这样网关容器里配置的host: tb才能正确解析到ThingsBoard应用的IP地址。网络名thingsboard_default是由之前docker-compose up自动创建的你可以通过docker network ls查看确认。-p 1883:1883: 将容器内的1883端口映射到宿主机的1883端口。这样外部设备才能连接到这个MQTT服务。-v ~/tb-gateway/config:/config: 将我们刚刚准备好的配置目录挂载到容器的/config路径下。容器会读取里面的tb_gateway.yaml和mqtt.json。thingsboard/tb-gateway: 使用的镜像名。运行后查看网关容器日志确认连接成功。docker logs -f tb-gateway在日志中你应该能看到类似“Gateway connected to ThingsBoard”和“MQTT Broker Connector started”的信息。同时回到ThingsBoard网页的“设备”列表你应该能看到你创建的网关设备的状态变成了“在线”一个绿色的小圆点。这表明网关服务已经成功启动并且连接到了ThingsBoard平台。5. 全链路测试从模拟设备到数据可视化平台和网关都跑起来了现在我们来做个端到端的测试模拟一个温度湿度传感器通过MQTT协议经由网关将数据上报到ThingsBoard并最终展示在仪表盘上。这个流程能帮你彻底理解整个数据流转路径。5.1 使用MQTT客户端模拟设备上报我们不需要真实的硬件用命令行工具mosquitto_pub就能模拟。首先确保安装了它在Ubuntu子系统中sudo apt-get install -y mosquitto-clients假设我们的传感器设备名叫“LivingRoom_Sensor_01”设备类型是“DHT22”。它要上报温度和湿度数据。根据网关mqtt.json的配置它需要向主题/sensor/data发布一个符合特定格式的JSON消息。执行下面的命令来发布一条消息mosquitto_pub -h localhost -p 1883 -t /sensor/data -m {deviceName:LivingRoom_Sensor_01, deviceType:DHT22, temperature:25.6, humidity:60.5}命令分解-h localhost: MQTT服务器地址就是我们的网关。-p 1883: 端口。-t /sensor/data: 主题必须和配置文件中的topicFilter一致。-m: 消息内容是一个JSON字符串。其中deviceName和deviceType字段用于网关识别和创建设备temperature和humidity是遥测数据。5.2 在ThingsBoard中验证数据接收发布命令执行后如果一切正常数据会经过网关处理转发到ThingsBoard。刷新ThingsBoard的“设备”页面。你应该能看到列表中多了一个名为“LivingRoom_Sensor_01”的设备其类型是“DHT22”。这就是网关根据消息自动创建设备的功能非常方便。点击“LivingRoom_Sensor_01”设备进入详情页。切换到“最新遥测”标签页。在这里你应该能看到刚刚上报的“temperature”和“humidity”两个键及其对应的值25.6和60.5以及数据到达的时间戳。这意味着数据链路已经完全打通设备-网关-平台这条通路是畅通的。5.3 创建仪表盘进行数据可视化看到原始数据还不够直观ThingsBoard强大的仪表盘功能可以让我们把数据变成图表。在左侧导航栏进入“仪表板”-“仪表板组”-“所有”。点击“”号创建一个新的仪表板命名为“家庭环境监控”。进入这个新建的仪表板点击右上角的“编辑”按钮铅笔图标进入编辑模式。点击大画布上的“添加新部件”按钮。在部件库中选择“图表”类别里面有很多图表类型。我们选择一个“时间序列折线图”。在部件的配置面板中最关键的是设置“数据源”。类型选择“设备”。设备从列表中选择我们刚刚创建的“LivingRoom_Sensor_01”。数据点击“添加数据键”选择“temperature”。再添加一个选择“humidity”。这样图表就会同时显示这两个数据序列。你可以调整图表的标题、颜色、时间范围等。配置好后点击“添加”按钮将部件放置到画布上。用同样的方法可以再添加一个“数字卡片”部件来显示当前的最新数值。编辑完成后点击右上角的“保存”按钮然后退出编辑模式。现在你的仪表盘上就有一个实时显示温湿度变化的图表了。你可以再次运行几次mosquitto_pub命令模拟上报新的数据记得改变温度和湿度的数值然后观察仪表盘上的图表是否会实时更新。6. 部署进阶配置、优化与故障排查基础功能跑通后我们还需要关注一些生产环境中会遇到的问题比如配置持久化、性能调优和日常运维。6.1 关键配置详解与持久化数据库数据持久化在最初的docker-compose.yml中ThingsBoard已经通过volumes配置将PostgreSQL的数据目录/var/lib/postgresql/data映射到了宿主机的一个命名卷通常是thingsboard_postgres-data。这意味着数据库文件实际存储在WSL2的虚拟磁盘中即使删除tb-postgres容器只要卷还在数据就不会丢。你可以通过docker volume ls查看和管理这些卷。ThingsBoard配置文件定制ThingsBoard应用本身有很多可配置项比如邮件服务器用于发送告警、租户配置等。这些配置可以通过环境变量或挂载配置文件的方式注入。在docker-compose.yml里tb服务通常已经引用了.env文件。对于更复杂的配置你可以修改docker-compose.yml在tb服务下添加volumes映射将宿主机上自定义的thingsboard.yml配置文件挂载到容器的/usr/share/thingsboard/conf/thingsboard.yml。但要注意直接修改镜像内的配置文件需要清楚配置结构建议先参考官方文档。网关配置热重载ThingsBoard Gateway支持远程配置和配置热重载。在我们前面的配置中为了简化关闭了这些功能remoteConfiguration: false。在生产环境你可以启用它并在ThingsBoard的规则链中创建“网关事件”规则节点来动态下发配置给网关实现集中管理。这是一个高级功能可以极大简化大规模网关部署的管理成本。6.2 性能优化与资源监控调整JVM参数ThingsBoard是Java应用在容器中运行可以通过环境变量调整JVM堆内存大小以适应你的硬件资源。编辑docker-compose.yml在tb服务的environment部分添加或修改如下变量environment: ... - JAVA_OPTS-Xmx1024m -Xms1024m这里将最大堆内存-Xmx和初始堆内存-Xms都设置为1024MB。你可以根据你的机器内存进行调整例如4GB内存的机器可以设为-Xmx2g -Xms2g。Redis缓存优化Redis默认配置对于测试够用。如果设备连接数巨大上万可能需要调整Redis的内存淘汰策略maxmemory-policy和大小maxmemory。这需要自定义Redis的配置文件并挂载到tb-redis容器中。监控容器状态使用docker stats命令可以实时查看所有容器的CPU、内存、网络IO使用情况。docker stats tb tb-postgres tb-redis tb-gateway定期检查日志特别是ThingsBoard的日志可以及时发现潜在错误。# 查看最近100行日志 docker-compose logs --tail100 tb # 持续查看网关日志 docker logs -f tb-gateway6.3 常见问题与排查实录在实际操作中你可能会遇到以下问题。这里记录了我的排查思路和解决方法。问题1访问localhost:8080无法打开ThingsBoard页面。排查步骤docker-compose ps检查tb容器状态是否为 “Up”。如果不是用docker-compose logs tb查看启动错误日志。检查端口是否被占用在Windows PowerShell中运行netstat -ano | findstr :8080。如果被占用可以修改docker-compose.yml中tb服务的端口映射例如改为- 18080:8080然后访问localhost:18080。确认WSL2网络有时Windows防火墙会阻止。尝试在WSL2的Ubuntu内运行curl http://localhost:8080如果这里能通但Windows浏览器不通可能是Windows防火墙问题暂时关闭防火墙测试或添加入站规则。问题2网关日志显示 “Connection refused” 或 “Failed to connect to ThingsBoard”。排查步骤检查网络确保tb-gateway容器和tb容器在同一个Docker网络中。运行docker inspect tb-gateway和docker inspect thingsboard_tb_1查看它们的NetworkSettings.Networks部分网络名称应该相同如thingsboard_default。检查配置确认tb_gateway.yaml中的host设置。在同一个Docker网络中应使用服务名tb。如果网关容器是单独用docker run启动且未指定网络它会在默认的bridge网络无法通过服务名解析。这就是为什么我们启动时要用--network thingsboard_default。检查ThingsBoard服务在WSL2内运行curl http://tb:8080看是否能访问到ThingsBoard。同时检查ThingsBoard容器日志看是否有网关连接尝试被拒绝的错误。问题3设备数据上报后在ThingsBoard中看不到设备或遥测数据。排查步骤检查网关日志docker logs tb-gateway。查看MQTT连接器是否启动以及当模拟设备发布消息时网关是否有相应的处理日志如“Processing message from topic...”。检查MQTT主题和消息格式确保设备发布的消息主题与mqtt.json中的topicFilter完全一致。确保JSON格式正确且包含deviceName字段。检查网关访问令牌在ThingsBoard设备列表中找到网关设备确认其“访问令牌”与tb_gateway.yaml中配置的accessToken完全一致注意不要有空格。检查设备自动创建在ThingsBoard的设备列表页面尝试搜索设备名。有时设备可能因为名称问题未被正确创建。可以尝试在mqtt.json的converter中明确指定deviceNameTopicExpression或使用更简单的设备名。问题4Docker容器占用磁盘空间过大。原因与解决Docker运行久了会积累很多无用的镜像、停止的容器和缓存。定期清理是必要的。# 删除所有已停止的容器 docker container prune -f # 删除所有未被任何容器引用的镜像悬空镜像 docker image prune -f # 删除所有未被使用的卷谨慎确保卷内数据已备份 docker volume prune -f # 删除构建缓存适用于自己构建镜像的情况 docker builder prune -f对于ThingsBoard最大的空间占用通常是PostgreSQL的数据卷。除非确定不再需要否则不要清理thingsboard_postgres-data卷。通过以上步骤你应该已经拥有了一个在Windows上稳定运行的、包含核心平台和网关的完整ThingsBoard测试环境。这个环境隔离性好易于维护和销毁非常适合进行物联网应用的原型开发、协议测试和学习。记住对于生产部署还需要考虑数据备份、网络安全、高可用架构等更多因素但本地这个Docker化环境无疑是你迈向更复杂部署的绝佳起点。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进