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

537 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 包**:
```xml
<dependencies>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>application</artifactId>
<version>${project.version}</version>
<classifier>deb</classifier>
<type>deb</type>
<scope>provided</scope>
</dependency>
</dependencies>
```
2. **复制 DEB 包到构建目录**:
```xml
<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>
```
3. **复制 Docker 配置文件**:
```xml
<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>
```
4. **构建 Docker 镜像**:
```xml
<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`
```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.xml``packaging/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 包**:
```xml
<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>
```
2. **复制 DEB 包**:
```xml
<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>
```
3. **构建 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. **前端构建**:
```xml
<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>
```
2. **提取 UI 文件**:
```xml
<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>
```
3. **Dockerfile**: 使用 Node.js 基础镜像,运行前端服务
### 3.4 JS Executor 服务
**位置**: `msa/js-executor/`
#### 3.4.1 Dockerfile
**文件**: `msa/js-executor/docker/Dockerfile`
```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 构建所有组件
```bash
# 从项目根目录执行
./build.sh
# 或者使用 Maven
mvn clean install -DskipTests
```
### 4.2 构建特定组件
```bash
# 构建特定模块
./build.sh msa/tb-node,msa/web-ui
# 或者
mvn clean install -DskipTests --projects msa/tb-node,msa/web-ui
```
### 4.3 构建并推送 Docker 镜像
```bash
# 构建并推送镜像
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`
```bash
#!/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 并行构建
```bash
# 使用多线程构建
mvn -T4 clean install -DskipTests
```
### 9.2 跳过 Docker 构建
```bash
# 只构建代码,不构建 Docker 镜像
mvn clean install -DskipTests -Ddockerfile.skip=true
```
### 9.3 增量构建
```bash
# 只构建变更的模块
mvn clean install -DskipTests --projects msa/tb-node
```
## 10. 常见问题
### 10.1 DEB 包找不到
**原因**: application 模块没有先构建
**解决**: 先构建 application 模块
```bash
mvn clean install -DskipTests --projects application
```
### 10.2 Docker 构建失败
**原因**: Docker daemon 未运行或权限不足
**解决**:
```bash
# 检查 Docker 状态
docker ps
# 确保用户在 docker 组中
sudo usermod -aG docker $USER
```
### 10.3 前端构建失败
**原因**: Node.js 版本不匹配或网络问题
**解决**:
```bash
# 使用正确的 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 镜像,便于部署和管理。