背景
我自定义了thingsboard的后端并且在postgres数据库添加了几个表,如果基于官方镜像修改极其困难
由于我对于在idea中通过maven插件创建docker镜像不怎么熟悉,于是决定通过jar包的方式自己手动创建容器
需要创建的容器有:
- postgres数据库
- thingsboard单体项目
注:理解接下来的内容需要一定的bash命令和docker基础
步骤
创建postgres官方容器(自行完成)并拷贝postgres数据库
我需要从windows拷贝到ubuntu上,首先我在ubuntu中创建了postgres的官方镜像并且挂载了对应的data目录,所以接着只要用windows上的data目录替换ubuntu上的data目录即可,但是我出现了locale无法匹配的问题
因为我windows安装时选择了简体中文的语言,locale为Chinese (Simplified)_China.936,而采用上述方式会导致容器无法识别locale,所以我又在拷贝前先把data目录里的配置文件中locale给修改成了镜像的locale,但是没有用,无论怎么搞最后数据库里数据表的locale还是无法和容器匹配
如果你的locale和官方的一样的话可以试一试直接拷贝data目录,如果不一样的话可以使用postgres自带的pg_dump和psql工具通过sql文件拷贝
首先到你的postgres的安装目录的bin目录,会有一个pg_dump.exe文件,在bin目录下使用管理员权限打开命令行,输入以下命令(不使用管理员会导致permission denied)
./pg_dump.exe -U your_username -d your_database_name -f backup.sql
然后需要输入数据库密码。username和database_name替换为实际的数据库,我这里是postgres和thingsboard
然后你的bin目录下会出现一个backup.sql文件
接着你需要在容器里通过这个backup.sql文件把数据还原回来,所以接下来要把这个文件拷贝到容器内,这一步请自行完成(先把文件拷贝到ubuntu宿主机上,然后通过docker cp xxx xxx:xxx把文件拷贝到容器内的bin目录下)
拷贝到容器内后同时也要进入容器内部(使用docker exec -it xxx bash),然后同样也需要进入到postgres的bin目录下,官方镜像对应的bin目录在 /usr/bin
接着通过以下命令还原数据
psql -U your_username -d your_database_name -f backup.sql
同样的,username和database_name替换为实际的名称,这里backup.sql要替换为实际的文件路径。输入完执行,拷贝完成。此时postgres容器已完成创建
打包thingsboard的jar包
众所周知thingsboard的打包过程极其令人烦躁的,需要protobuf相关插件,npm,yarn还有一个稳定的网络,这里不详细说明打包过程,如果遇到了问题网上现有的博客可以对症下药。
我打包的时候需要使用命令行的方式install,如果使用idea的maven工具install得不到thingsboard-3.6.2-boot.jar,最后得到的jar包大小为250MB左右
打包完成后首先试着本地运行,使用java -jar的方式,然后就报错了:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mailConfigTemplateController' defined in URL [jar:file:/E:/Project/thingsboard-release-3.6/application/target/thingsboard-3.6.2-boot.jar!/BOOT-INF/classes!/org/thingsboard/server/controller/MailConfigTemplateController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultTbMailConfigTemplateService': Invocation of init method failed; nested exception is java.io.FileNotFoundException: class path resource [templates/mail_config_templates.json] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/E:/Project/thingsboard-release-3.6/application/target/thingsboard-3.6.2-boot.jar!/BOOT-INF/classes!/templates/mail_config_templates.json
是一个关于读取不到文件的报错,仔细观察后发现报错中有不合理的文件路径:
jar:file:/E:/Project/thingsboard-release-3.6/xxx
这里使用了jar的路径+绝对路径的方式,那肯定是不对的,最后在源码里找到了读取这个文件的类: DefaultTbMailConfigTemplateService
其中有一个postConstruct方法:
@PostConstruct
private void postConstruct() throws IOException {
mailConfigTemplates = JacksonUtil.toJsonNode(new ClassPathResource("/templates/mail_config_templates.json").getFile());
}
把这段代码改为:
@PostConstruct
private void postConstruct() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
try (InputStream inputStream = new ClassPathResource("/templates/mail_config_templates.json").getInputStream()) {
mailConfigTemplates = objectMapper.readTree(inputStream);
}
}
重新install,再次运行jar包,发现正常启动了
创建thingsboard的docker镜像并启动容器
Dockerfile:
FROM openjdk:11
EXPOSE 8080
ADD *.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java", "-jar", "/app.jar"]
创建镜像:docker build -t thingsboard/custom .
docker-compose.yml:
version: '3.0'
services:
tb:
restart: always
image: "thingsboard/custom"
container_name: tb
ports:
- "8080:8080"
- "1883:1883"
- "7070:7070"
- "5683-5688:5683-5688/udp"
environment:
TB_QUEUE_TYPE: in-memory
SPRING_DATASOURCE_URL: jdbc:postgresql://172.20.0.1:5432/thingsboard
SPRING_DATASOURCE_USERNAME: xxx
SPRING_DATASOURCE_PASSWORD: xxx
networks:
tb-network:
ipv4_address: 172.20.0.5
networks:
tb-network:
driver: bridge
ipam:
config:
- subnet: ${SUBNET:-172.20.0.0/16}
其中SPRING_DATASOURCE_URL为postgres的url,这里设置了docker网络,thingsboard通过访问宿主机的5432端口来访问postgres,根据实际情况改变
输入docker-compose up -d,启动成功!