thingsboard/summary/06-Docker镜像构建流程分析.md

13 KiB
Raw Permalink Blame History

ThingsBoard Docker 镜像构建流程分析

1. 概述

ThingsBoard 的 Docker 镜像构建采用 Maven + Dockerfile 的方式,先通过 Maven 编译源码并打包成 DEB 包,然后使用 Dockerfile 将 DEB 包安装到 Docker 镜像中。

2. 构建流程总览

源码编译 -> Maven 打包 -> DEB 包生成 -> Dockerfile 构建 -> Docker 镜像

3. 核心组件构建流程

3.1 tb-node (核心服务/规则引擎)

位置: msa/tb-node/

3.1.1 Maven 构建配置

文件: msa/tb-node/pom.xml

关键步骤:

  1. 依赖 DEB 包:
<dependencies>
    <dependency>
        <groupId>org.thingsboard</groupId>
        <artifactId>application</artifactId>
        <version>${project.version}</version>
        <classifier>deb</classifier>
        <type>deb</type>
        <scope>provided</scope>
    </dependency>
</dependencies>
  1. 复制 DEB 包到构建目录:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-tb-deb</id>
            <phase>package</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>org.thingsboard</groupId>
                        <artifactId>application</artifactId>
                        <classifier>deb</classifier>
                        <type>deb</type>
                        <destFileName>${pkg.name}.deb</destFileName>
                        <outputDirectory>${project.build.directory}</outputDirectory>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 复制 Docker 配置文件:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-docker-config</id>
            <phase>process-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}</outputDirectory>
                <resources>
                    <resource>
                        <directory>docker</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 构建 Docker 镜像:
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>build-docker-image</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>build</goal>
            </goals>
            <configuration>
                <skip>${dockerfile.skip}</skip>
                <repository>${docker.repo}/${docker.name}</repository>
                <verbose>true</verbose>
                <contextDirectory>${project.build.directory}</contextDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

3.1.2 Dockerfile

文件: msa/tb-node/docker/Dockerfile

# 基础镜像OpenJDK 17
FROM thingsboard/openjdk17:bookworm-slim

# 复制文件到临时目录
COPY logback.xml start-tb-node.sh ${pkg.name}.deb /tmp/

# 安装 DEB 包并配置
RUN chmod a+x /tmp/*.sh \
    && mv /tmp/start-tb-node.sh /usr/bin && \
    (yes | dpkg -i /tmp/${pkg.name}.deb) && \
    rm /tmp/${pkg.name}.deb && \
    mv /tmp/logback.xml ${pkg.installFolder}/conf && \
    chown -R ${pkg.user}:${pkg.user} ${pkg.installFolder}/conf/logback.xml && \
    (systemctl --no-reload disable --now ${pkg.name}.service > /dev/null 2>&1 || :) && \
    chown -R ${pkg.user}:${pkg.user} /tmp && \
    chmod 555 ${pkg.installFolder}/bin/${pkg.name}.jar

USER ${pkg.user}

CMD ["start-tb-node.sh"]

关键点:

  • 使用 dpkg -i 安装 DEB 包
  • DEB 包会将应用安装到 /usr/share/thingsboard/
  • 复制启动脚本和配置文件
  • 设置正确的用户权限

3.1.3 DEB 包生成

位置: application/pom.xmlpackaging/java/

DEB 包是通过 Gradle 构建的:

  1. Gradle 构建脚本: packaging/java/build.gradle
  2. 构建阶段: 在 Maven 的 package 阶段调用 Gradle
  3. 输出: application/target/thingsboard-{version}-boot.deb

DEB 包包含:

  • JAR 文件Spring Boot 打包的应用)
  • 配置文件
  • 启动脚本
  • 系统服务文件

3.2 传输服务 (MQTT/HTTP/CoAP/LWM2M/SNMP)

位置: msa/transport/{protocol}/

3.2.1 Maven 构建配置

文件: msa/transport/mqtt/pom.xml (以 MQTT 为例)

关键步骤:

  1. 依赖传输模块的 DEB 包:
<dependencies>
    <dependency>
        <groupId>org.thingsboard.transport</groupId>
        <artifactId>mqtt</artifactId>
        <version>${project.version}</version>
        <classifier>deb</classifier>
        <type>deb</type>
        <scope>provided</scope>
    </dependency>
</dependencies>
  1. 复制 DEB 包:
<execution>
    <id>copy-tb-mqtt-transport-deb</id>
    <phase>package</phase>
    <goals>
        <goal>copy</goal>
    </goals>
    <configuration>
        <artifactItems>
            <artifactItem>
                <groupId>org.thingsboard.transport</groupId>
                <artifactId>mqtt</artifactId>
                <classifier>deb</classifier>
                <type>deb</type>
                <destFileName>${pkg.name}.deb</destFileName>
                <outputDirectory>${project.build.directory}</outputDirectory>
            </artifactItem>
        </artifactItems>
    </configuration>
</execution>
  1. 构建 Docker 镜像: 与 tb-node 类似

3.2.2 传输模块 DEB 包生成

位置: transport/mqtt/pom.xml

传输模块的 DEB 包也是通过 Gradle 构建的,构建流程与 application 模块类似。

3.3 Web UI 服务

位置: msa/web-ui/

3.3.1 构建流程

文件: msa/web-ui/pom.xml

关键步骤:

  1. 前端构建:
<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <executions>
        <!-- 安装 Node.js 和 Yarn -->
        <execution>
            <id>install node and yarn</id>
            <goals>
                <goal>install-node-and-yarn</goal>
            </goals>
            <configuration>
                <nodeVersion>v22.18.0</nodeVersion>
                <yarnVersion>v1.22.22</yarnVersion>
            </configuration>
        </execution>
        
        <!-- 安装依赖 -->
        <execution>
            <id>yarn install</id>
            <goals>
                <goal>yarn</goal>
            </goals>
            <configuration>
                <arguments>install --non-interactive</arguments>
            </configuration>
        </execution>
        
        <!-- 构建前端 -->
        <execution>
            <id>yarn pkg</id>
            <goals>
                <goal>yarn</goal>
            </goals>
            <phase>compile</phase>
            <configuration>
                <arguments>run pkg</arguments>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 提取 UI 文件:
<execution>
    <id>extract-web-ui</id>
    <goals>
        <goal>unpack</goal>
    </goals>
    <configuration>
        <artifactItems>
            <artifactItem>
                <groupId>org.thingsboard</groupId>
                <artifactId>ui-ngx</artifactId>
                <type>jar</type>
                <outputDirectory>${project.build.directory}/web</outputDirectory>
            </artifactItem>
        </artifactItems>
    </configuration>
</execution>
  1. Dockerfile: 使用 Node.js 基础镜像,运行前端服务

3.4 JS Executor 服务

位置: msa/js-executor/

3.4.1 Dockerfile

文件: msa/js-executor/docker/Dockerfile

FROM thingsboard/node:22.18.0-bookworm-slim

ENV NODE_ENV production
ENV DOCKER_MODE true

COPY start-js-executor.sh /tmp/

WORKDIR ${pkg.installFolder}

# 复制源代码和配置文件
COPY ["src/package.json", "src/yarn.lock", "./"]
COPY package/linux/conf ./conf
COPY package/linux/conf ./config
COPY src/api ./api
COPY src/queue ./queue
COPY src/config ./config
COPY src/server.js ./

# 安装依赖并设置权限
RUN chmod a+x /tmp/*.sh \
    && mv /tmp/start-js-executor.sh /usr/bin \
    && chown -R node:node ${pkg.installFolder} \
    && yarn install --production --non-interactive \
    && yarn cache clean --all

USER node

CMD ["start-js-executor.sh"]

特点: JS Executor 直接复制源代码,不需要 DEB 包。

4. 完整构建命令

4.1 构建所有组件

# 从项目根目录执行
./build.sh

# 或者使用 Maven
mvn clean install -DskipTests

4.2 构建特定组件

# 构建特定模块
./build.sh msa/tb-node,msa/web-ui

# 或者
mvn clean install -DskipTests --projects msa/tb-node,msa/web-ui

4.3 构建并推送 Docker 镜像

# 构建并推送镜像
mvn clean install -DskipTests -Ddockerfile.skip=false -Dpush-docker-image=true

5. 构建依赖关系

5.1 模块依赖顺序

1. common/* (公共模块)
   ↓
2. dao (数据访问层)
   ↓
3. application (主应用)
   ↓
4. transport/* (传输模块)
   ↓
5. ui-ngx (前端)
   ↓
6. msa/* (微服务镜像)

5.2 DEB 包生成顺序

  1. application 模块: 生成 thingsboard-{version}-boot.deb
  2. transport 模块: 生成 tb-{protocol}-transport-{version}.deb
  3. ui-ngx 模块: 生成 JAR 包(包含前端静态资源)

6. 构建产物位置

6.1 DEB 包

  • Application: application/target/thingsboard-{version}-boot.deb
  • Transport: transport/{protocol}/target/tb-{protocol}-transport-{version}.deb

6.2 Docker 镜像构建上下文

  • tb-node: msa/tb-node/target/
    • 包含: Dockerfile, DEB 包, 启动脚本, 配置文件
  • 传输服务: msa/transport/{protocol}/target/
    • 包含: Dockerfile, DEB 包, 启动脚本

6.3 Docker 镜像

构建完成后Docker 镜像会保存在本地:

  • thingsboard/tb-node:{version}
  • thingsboard/tb-mqtt-transport:{version}
  • thingsboard/tb-web-ui:{version}
  • 等等

7. 构建脚本详解

7.1 build.sh

位置: build.sh

#!/bin/bash

# 设置错误时退出
set -e

# 可以指定要构建的项目
PROJECTS=""

if [ "$1" ]; then
  PROJECTS="--projects $1"
fi

# 构建命令
MAVEN_OPTS="-Xmx1024m" NODE_OPTIONS="--max_old_space_size=4096" \
DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=0 \
mvn -T2 license:format clean install -DskipTests \
  $PROJECTS --also-make

关键参数:

  • -T2: 使用 2 个线程并行构建
  • --also-make: 同时构建依赖模块
  • -DskipTests: 跳过测试(加快构建速度)

8. 构建环境要求

8.1 必需工具

  • Java 17: 编译 Java 代码
  • Maven 3.6+: 构建工具
  • Docker: 构建 Docker 镜像
  • Node.js 22.18.0: 构建前端web-ui
  • Yarn 1.22.22: 前端包管理

8.2 系统要求

  • 内存: 至少 4GB推荐 8GB+
  • 磁盘空间: 至少 10GB 可用空间
  • 操作系统: Linux/macOSWindows 需要 WSL

9. 构建优化

9.1 并行构建

# 使用多线程构建
mvn -T4 clean install -DskipTests

9.2 跳过 Docker 构建

# 只构建代码,不构建 Docker 镜像
mvn clean install -DskipTests -Ddockerfile.skip=true

9.3 增量构建

# 只构建变更的模块
mvn clean install -DskipTests --projects msa/tb-node

10. 常见问题

10.1 DEB 包找不到

原因: application 模块没有先构建

解决: 先构建 application 模块

mvn clean install -DskipTests --projects application

10.2 Docker 构建失败

原因: Docker daemon 未运行或权限不足

解决:

# 检查 Docker 状态
docker ps

# 确保用户在 docker 组中
sudo usermod -aG docker $USER

10.3 前端构建失败

原因: Node.js 版本不匹配或网络问题

解决:

# 使用正确的 Node.js 版本
nvm use 22.18.0

# 清理缓存重试
cd ui-ngx && rm -rf node_modules && yarn install

11. 总结

ThingsBoard 的 Docker 镜像构建流程:

  1. 源码编译: Maven 编译 Java 代码
  2. 打包: 使用 Gradle 打包成 DEB 包Java 服务)或 JAR 包(前端)
  3. Docker 构建: 使用 dockerfile-maven-plugin 调用 Dockerfile 构建镜像
  4. 镜像生成: 最终生成 Docker 镜像

关键特点:

  • 使用 DEB 包作为中间产物,便于安装和配置
  • 采用 Maven 多模块项目结构,支持并行构建
  • 前端和 Java 服务采用不同的构建方式
  • 支持构建特定模块,提高构建效率

通过这个流程ThingsBoard 可以将复杂的多模块项目统一构建成 Docker 镜像,便于部署和管理。