Skip to content

Ubuntu系统部署 ThingsBoard 4.3.x ​

本文用 Docker Compose 在 Ubuntu 上部署 ThingsBoard CE 4.3.1.8。每种方式都给出完整可复制的 docker-compose.yml 与初始化命令;Compose 内容已对照 官方 Docker 安装文档(镜像 thingsboard/tb-node:4.3.1.8、postgres:18、bitnamilegacy/kafka:4.0)整理。

官方原生 deb 安装(非 Docker)见:Installing ThingsBoard CE on Ubuntu。本文聚焦 Docker,上手更快、回滚更简单。

0. 推荐环境 ​

操作系统(请按此选型) ​

优先级系统说明
推荐Ubuntu 24.04 LTS当前长期支持,官方文档明确支持,镜像与包源最省心
可用Ubuntu 22.04 LTS同样在官方 Ubuntu 安装指南支持列表中
可选Ubuntu 26.04 LTS官方已列入支持,新系统可试用
不建议非 LTS / 过旧的 20.04包源与 Docker 插件差异大,排错成本高

结论:生产与学习都优先选 Ubuntu 24.04 LTS(x86_64)。

硬件参考(官方量级) ​

场景CPU内存建议组合
开发 / PoC≥ 1 核≥ 4 GBTB + PostgreSQL(内存队列)
小生产≥ 2 核≥ 8 GBTB + PostgreSQL + Kafka
高吞吐 / 混合库≥ 4 核≥ 16 GBTB + PG + Kafka + Cassandra(Cassandra 很吃内存)

版本钉死(本文统一) ​

组件版本
ThingsBoard CEthingsboard/tb-node:4.3.1.8
PostgreSQLpostgres:18
Kafka(可选)bitnamilegacy/kafka:4.0
Cassandra(可选)cassandra:5.0

四种部署怎么选 ​

方式组成适用
ATB + PostgreSQL默认推荐:演示、开发、中小规模
BTB + PG + Kafka需要更稳的队列、为扩展做准备
CTB + PG + Cassandra时序进 Cassandra,实体仍在 PG(高写入)
DTB + PG + Kafka + Cassandra高吞吐生产向,资源要求最高

绝大多数人先跑方式 A。 Cassandra 堆内存默认很大,机器不够请用文末调小 -Xmx。


1. 安装 Docker(Ubuntu 24.04 / 22.04) ​

以下命令在 root 或带 sudo 的用户下执行。

bash
sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
docker --version
docker compose version

把当前用户加入 docker 组(可选,免 sudo;执行后需重新登录):

bash
sudo usermod -aG docker "$USER"

若 docker compose version 报错,可再试:sudo apt install -y docker-compose-plugin。下文统一使用 docker compose(Compose V2),不要用旧的 docker-compose。

国内拉镜像(可选) ​

若拉取 Docker Hub 很慢,可配置镜像加速后重启 Docker(镜像源会失效,请按当时可用源调整):

bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.1panel.live",
    "https://hub-mirror.c.163.com"
  ]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

工作目录:

bash
mkdir -p ~/thingsboard && cd ~/thingsboard

后面所有命令都在 ~/thingsboard 执行。


2. 方式 A:TB + PostgreSQL(推荐入门) ​

适合学习、PoC、中小流量。队列使用内置 In-Memory(Compose 中不写 TB_QUEUE_TYPE 即为默认)。

2.1 写入 compose ​

bash
cd ~/thingsboard
cat > docker-compose.yml <<'EOF'
services:
  postgres:
    restart: always
    image: "postgres:18"
    ports:
      - "5432"
    environment:
      POSTGRES_DB: thingsboard
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres-data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d thingsboard"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  thingsboard-ce:
    restart: always
    image: "thingsboard/tb-node:4.3.1.8"
    ports:
      - "8080:8080"
      - "7070:7070"
      - "1883:1883"
      - "8883:8883"
      - "5683-5688:5683-5688/udp"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
    environment:
      TB_SERVICE_ID: tb-ce-node
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: postgres
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres-data:
    name: tb-postgres-data
    driver: local
EOF

核对要点: POSTGRES_PASSWORD 与 SPRING_DATASOURCE_PASSWORD 必须一致;postgres:18 数据目录挂载为 /var/lib/postgresql(与官方一致,不要写成旧的 /var/lib/postgresql/data)。

生产请把 postgres 密码改成强密码,并同步改两处环境变量。

2.2 初始化库表(首次必做) ​

带演示数据:

bash
docker compose run --rm -e INSTALL_TB=true -e LOAD_DEMO=true thingsboard-ce

只要系统数据、不要 demo:

bash
docker compose run --rm -e INSTALL_TB=true thingsboard-ce

初始化容器会自动退出。

2.3 启动 ​

bash
docker compose up -d
docker compose logs -f thingsboard-ce

日志出现 Started ThingsboardServerApplication 后,浏览器打开:

text
http://服务器IP:8080

默认账号(登录后立刻改密):

角色邮箱密码需 LOAD_DEMO
系统管理员sysadmin@thingsboard.orgsysadmin否
租户管理员tenant@thingsboard.orgtenant是
客户用户customer@thingsboard.orgcustomer是

常用运维:

bash
docker compose ps
docker compose logs -f --tail 100 thingsboard-ce
docker compose down          # 停止(数据卷保留)
docker compose up -d         # 再启动

3. 方式 B:TB + PostgreSQL + Kafka ​

队列改为 Kafka,更接近生产用法。Compose 对齐官方 Docker 文档中的 Kafka 方案。

bash
cd ~/thingsboard
cat > docker-compose.yml <<'EOF'
services:
  postgres:
    restart: always
    image: "postgres:18"
    ports:
      - "5432"
    environment:
      POSTGRES_DB: thingsboard
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres-data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d thingsboard"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  kafka:
    restart: always
    image: bitnamilegacy/kafka:4.0
    ports:
      - "9092:9092"
      - "9093"
    environment:
      ALLOW_PLAINTEXT_LISTENER: "yes"
      KAFKA_CFG_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
      KAFKA_CFG_ADVERTISED_LISTENERS: "PLAINTEXT://:9092"
      KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT"
      KAFKA_CFG_INTER_BROKER_LISTENER_NAME: "PLAINTEXT"
      KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "false"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: "1"
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: "1"
      KAFKA_CFG_PROCESS_ROLES: "controller,broker"
      KAFKA_CFG_NODE_ID: "0"
      KAFKA_CFG_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: "0@kafka:9093"
      KAFKA_CFG_LOG_RETENTION_MS: "300000"
      KAFKA_CFG_SEGMENT_BYTES: "26214400"
    volumes:
      - kafka-data:/bitnami

  thingsboard-ce:
    restart: always
    image: "thingsboard/tb-node:4.3.1.8"
    ports:
      - "8080:8080"
      - "7070:7070"
      - "1883:1883"
      - "8883:8883"
      - "5683-5688:5683-5688/udp"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
    environment:
      TB_SERVICE_ID: tb-ce-node
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: postgres
      TB_QUEUE_TYPE: kafka
      TB_KAFKA_SERVERS: kafka:9092
    depends_on:
      postgres:
        condition: service_healthy
      kafka:
        condition: service_started

volumes:
  postgres-data:
    name: tb-postgres-data
    driver: local
  kafka-data:
    name: tb-ce-kafka-data
    driver: local
EOF

核对要点: TB_QUEUE_TYPE=kafka 且 TB_KAFKA_SERVERS=kafka:9092(容器服务名);Kafka 使用官方文档同款 bitnamilegacy/kafka:4.0 KRaft 单节点参数。

初始化与启动(与方式 A 相同):

bash
docker compose run --rm -e INSTALL_TB=true -e LOAD_DEMO=true thingsboard-ce
docker compose up -d
docker compose logs -f thingsboard-ce

4. 方式 C:TB + PostgreSQL + Cassandra(混合库) ​

实体在 PostgreSQL,时序在 Cassandra。适合高写入;内存建议 ≥ 16GB。下面默认把 Cassandra 堆调到 2G(原文 8G 容易把小机器打崩;有余量再加大)。

bash
cd ~/thingsboard
cat > docker-compose.yml <<'EOF'
services:
  postgres:
    restart: always
    image: "postgres:18"
    ports:
      - "5432"
    environment:
      POSTGRES_DB: thingsboard
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres-data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d thingsboard"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  cassandra:
    restart: always
    image: "cassandra:5.0"
    ports:
      - "9042"
    environment:
      CASSANDRA_CLUSTER_NAME: "ThingsBoard Cluster"
      JAVA_TOOL_OPTIONS: >-
        -Xms2G -Xmx2G
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.port=7199
        -Dcom.sun.management.jmxremote.rmi.port=7199
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Djava.rmi.server.hostname=127.0.0.1
    volumes:
      - cassandra-data:/var/lib/cassandra
    healthcheck:
      test: ["CMD-SHELL", "nodetool status | grep -E '^UN\\s+' || exit 1"]
      interval: 30s
      timeout: 15s
      retries: 30
      start_period: 180s

  thingsboard-ce:
    restart: always
    image: "thingsboard/tb-node:4.3.1.8"
    ports:
      - "8080:8080"
      - "7070:7070"
      - "1883:1883"
      - "8883:8883"
      - "5683-5688:5683-5688/udp"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
    environment:
      TB_SERVICE_ID: tb-ce-node
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: postgres
      DATABASE_TS_TYPE: cassandra
      CASSANDRA_URL: cassandra:9042
    depends_on:
      postgres:
        condition: service_healthy
      cassandra:
        condition: service_healthy

volumes:
  postgres-data:
    name: tb-postgres-data
    driver: local
  cassandra-data:
    name: tb-cassandra-data
    driver: local
EOF

核对要点: DATABASE_TS_TYPE=cassandra + CASSANDRA_URL=cassandra:9042;先等 Cassandra healthcheck 通过再装库。

因 Cassandra 启动慢,建议先拉起依赖再初始化:

bash
docker compose up -d postgres cassandra
docker compose ps
# 等到 cassandra healthy 后再执行:
docker compose run --rm -e INSTALL_TB=true -e LOAD_DEMO=true thingsboard-ce
docker compose up -d
docker compose logs -f thingsboard-ce

机器内存充足时,可将 JAVA_TOOL_OPTIONS 中的 -Xms2G -Xmx2G 改为 -Xms4G -Xmx4G 或更高。


5. 方式 D:TB + PostgreSQL + Kafka + Cassandra ​

高吞吐组合:队列 Kafka + 时序 Cassandra。资源要求最高。

bash
cd ~/thingsboard
cat > docker-compose.yml <<'EOF'
services:
  postgres:
    restart: always
    image: "postgres:18"
    ports:
      - "5432"
    environment:
      POSTGRES_DB: thingsboard
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres-data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d thingsboard"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  kafka:
    restart: always
    image: bitnamilegacy/kafka:4.0
    ports:
      - "9092:9092"
      - "9093"
    environment:
      ALLOW_PLAINTEXT_LISTENER: "yes"
      KAFKA_CFG_LISTENERS: "PLAINTEXT://:9092,CONTROLLER://:9093"
      KAFKA_CFG_ADVERTISED_LISTENERS: "PLAINTEXT://:9092"
      KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT"
      KAFKA_CFG_INTER_BROKER_LISTENER_NAME: "PLAINTEXT"
      KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "false"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: "1"
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: "1"
      KAFKA_CFG_PROCESS_ROLES: "controller,broker"
      KAFKA_CFG_NODE_ID: "0"
      KAFKA_CFG_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: "0@kafka:9093"
      KAFKA_CFG_LOG_RETENTION_MS: "300000"
      KAFKA_CFG_SEGMENT_BYTES: "26214400"
    volumes:
      - kafka-data:/bitnami

  cassandra:
    restart: always
    image: "cassandra:5.0"
    ports:
      - "9042"
    environment:
      CASSANDRA_CLUSTER_NAME: "ThingsBoard Cluster"
      JAVA_TOOL_OPTIONS: >-
        -Xms2G -Xmx2G
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.port=7199
        -Dcom.sun.management.jmxremote.rmi.port=7199
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Djava.rmi.server.hostname=127.0.0.1
    volumes:
      - cassandra-data:/var/lib/cassandra
    healthcheck:
      test: ["CMD-SHELL", "nodetool status | grep -E '^UN\\s+' || exit 1"]
      interval: 30s
      timeout: 15s
      retries: 30
      start_period: 180s

  thingsboard-ce:
    restart: always
    image: "thingsboard/tb-node:4.3.1.8"
    ports:
      - "8080:8080"
      - "7070:7070"
      - "1883:1883"
      - "8883:8883"
      - "5683-5688:5683-5688/udp"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
    environment:
      TB_SERVICE_ID: tb-ce-node
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: postgres
      TB_QUEUE_TYPE: kafka
      TB_KAFKA_SERVERS: kafka:9092
      DATABASE_TS_TYPE: cassandra
      CASSANDRA_URL: cassandra:9042
    depends_on:
      postgres:
        condition: service_healthy
      kafka:
        condition: service_started
      cassandra:
        condition: service_healthy

volumes:
  postgres-data:
    name: tb-postgres-data
    driver: local
  kafka-data:
    name: tb-ce-kafka-data
    driver: local
  cassandra-data:
    name: tb-cassandra-data
    driver: local
EOF
bash
docker compose up -d postgres kafka cassandra
docker compose ps
docker compose run --rm -e INSTALL_TB=true -e LOAD_DEMO=true thingsboard-ce
docker compose up -d
docker compose logs -f thingsboard-ce

6. 端口与防火墙 ​

按需放行(云安全组 + ufw):

端口用途
TCP 8080Web UI / REST
TCP 1883 / 8883MQTT / MQTTS
UDP 5683–5688CoAP / LwM2M
TCP 7070Edge RPC

示例:

bash
sudo ufw allow 8080/tcp
sudo ufw allow 1883/tcp
sudo ufw reload

PostgreSQL / Cassandra / Kafka 端口在 Compose 里多为「仅映射容器端口、不绑死宿主机公布端口」或仅内部访问;不要把 5432/9042 无防护暴露公网。


7. 可选:开启 ThingsBoard Web SSL ​

在方式 A 基础上增加证书挂载与 SSL 环境变量。先准备自签证书(生产请换成正式证书):

bash
cd ~/thingsboard
mkdir -p keys
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout keys/server_key.pem \
  -out keys/server.pem \
  -subj "/CN=localhost"

将 thingsboard-ce 服务改为类似(其余 postgres 服务保持不变):

yaml
  thingsboard-ce:
    restart: always
    image: "thingsboard/tb-node:4.3.1.8"
    ports:
      - "8080:8080"
      - "7070:7070"
      - "1883:1883"
      - "8883:8883"
      - "5683-5688:5683-5688/udp"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
    environment:
      TB_SERVICE_ID: tb-ce-node
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: postgres
      SSL_ENABLED: "true"
      SSL_PEM_CERT: /keys/server.pem
      SSL_PEM_KEY: /keys/server_key.pem
    volumes:
      - ./keys:/keys:ro
      - thingsboard-ce-logs:/var/log/thingsboard
    depends_on:
      postgres:
        condition: service_healthy

并在 volumes: 下增加:

yaml
  thingsboard-ce-logs:
    name: tb-logs
    driver: local

改完后重新 docker compose up -d。浏览器访问 https://服务器IP:8080(自签证书需信任例外)。


8. 排错速查 ​

现象处理
docker compose 不存在安装 docker-compose-v2 / docker-compose-plugin
拉镜像失败配镜像加速或代理,检查 DNS
初始化失败先 docker compose logs postgres;保证 PG healthy
Cassandra 一直 starting内存不够;先降 -Xmx,或换方式 A/B
8080 打不开docker compose ps、看 TB 日志、查安全组 / ufw
改密码后连不上库POSTGRES_PASSWORD 与 SPRING_DATASOURCE_PASSWORD 不一致
换部署方式复用旧卷结构不兼容时需换 volume 名或 docker volume rm(会丢数据)

彻底删除本目录栈(含数据卷,慎用):

bash
docker compose down -v

9. 小结 ​

  1. 系统选 Ubuntu 24.04 LTS(或 22.04 LTS)。
  2. 入门用方式 A(TB + PG),复制第 2 节三条命令即可跑通。
  3. Kafka / Cassandra 组合已按官方镜像与关键环境变量校核;Cassandra 默认堆改为 2G,避免小机器 OOM。
  4. 先 INSTALL_TB 再 up -d,不要跳过初始化。

下一步 ​