掘金 后端 ( ) • 2024-04-28 17:07

🧭: javajar包jdk8html2image,容器化部署

容器默认UTC时区和我们中国使用的东八区CST相差8个小时,所以在使用容器部署服务时,我们都会在docker命令或者dockerfile或者docker-compose再或者K8S中处理时区问题,以免时间不一致导致出现问题。

今天本文主要是描述下,在开发同事使用html2image转换图片时,遇到中文字体变成了方块的解决办法。

html2image的简单介绍:
html2image是一个在unix下截取html页面的内容生成图片的工具,可以截取静态和动态的(即通过javascript代码执行后生成的)html页面。
只需在命令行输入一条执行命令就可以截下任意的html页面,方便,易用。目前支持的格式有jpg,png和bmp三种格式。
如果要使用更多的功能则需要付费,比如对firefox3的支持和对图片的压缩质量的控制。
详细的内容可以查阅这个网址:http://www.guangmingsoft.net/htmlsnapshot/html2image.htm

🎈时区调整

首先是解决+8时区问题吧。这个网上有很多前辈写过了,我再将我实际操作的过程写出来供后来者查看。

FROM openjdk:8-jdk-alpine

# 增加阿里的仓库源 --- 解决下载慢问题
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories

# 解决时差8小时问题
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata \
        && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
        && echo $TZ > /etc/timezone

这是我在解决本次遇到问题时,基于jdk8镜像 openjdk:8-jdk-alpine 来编写dockerfile中关于时区的设置。

还有别的办法么?🫠当然啦。🤪

其实正如上面提到的,并不是非要在构建镜像这一步就要搞定它,完全还可以在docker run 命令时 传参,还可以在docker-compose中,对于容器服务配置变量的方法或者挂载本地时区文件等方式来实现更改时区。 到底怎么做,完全可以看你实际需要和处理习惯了。

举例:
    environment:                        # 设置环境变量,相当于docker run命令中的-e
      TZ: Asia/Shanghai
      LANG: en_US.UTF-8
      MYSQL_ROOT_PASSWORD: "123456"         # 设置root用户密码
      MYSQL_DATABASE: jacklove              # 初始化的数据库名称
    privileged: true
    user: root
    ports:                              # 映射端口
      - "3306:3306"
      
 docker exec -it mysql8 sh -c "date"
Sun Apr 28 15:11:15 CST 2024

我今天处理这个,就为了节省后续自动化中要输入的命令(懒得一个字母都不想多打🤪),并且对于其他项目中的java服务也可以直接拿来套用即可,所以我肯定会直接做一个拿来即用的镜像了。 说完上面的,那么就要解决开发人员遇到的问题了。 首先是网上查询这个小可爱,有没有别人也遇到这类问题。果然是有的。感谢互联网

🎈处理中文乱码

那么我们直接跟着做下看能否解决吧。

由于我是需要将该jar包打包到上面jdk镜像中运行,所以添加字体文件就要放到镜像中(这不XX嘛) 那么在dockerfile中开始编写吧

#创建字体存放目录
RUN mkdir -p /usr/share/fonts/cn /usr/lib/jvm/java-1.8-openjdk/jre/lib/fonts/fallback/
# 安装中文字体,微软雅黑字体
COPY ./msyhbd.ttc /usr/share/fonts/cn/msyhbd.ttc
COPY ./msyhbd.ttc /usr/lib/jvm/java-1.8-openjdk/jre/lib/jre/lib/fonts/fallback/msyhbd.ttc
RUN  apk add --no-cache ttf-dejavu fontconfig \
        && fc-cache -f \
        && rm -rf /var/cache/apk/*
        

解释一下: 创建目录是必须的,实测如果不创建,而指向到不存在的目录是无法将文件放置进去(没道理啊,明明docker可以这样的,有人能告诉我why?) 复制文件到上面创建的指定目录去,没什么好说的。 安装字体管理工具命令,这个也是必要的,不然我们只是放进去微软雅黑字体是不行的(个人测试),还要使用fc-cache -f 强制重新建立系统字体缓存,以确保我们新加入的字体被正确的添加到系统字体缓存中 最后就是删除apk安装后的缓存了,减小整个镜像文件大小。

🎈构建镜像

通过以上内容的操作,接下来我们就要进行之前讲过的基本命令中 docker build来构建镜像了。

docker build -t registry.cn-shanghai.aliyuncs.com/jacklove/openjdk:8-TZ-CN .
# -t 打标签作用,要符合你接下来将这个容器上传到私有化镜像仓库还是github或者阿里云等其他镜像仓库的规则哦。不然是上传不上去的,
#例如上面的地址是我个人创建了一个名叫jacklove的命名空间,如果我要将这个镜像打包成一个不存在的命名空间存放这个镜像,例如registry.cn-shanghai.aliyuncs.com/rocketmq/openjdk:8-TZ-CN,而我并没有在阿里云的镜像仓库中创建rocketmq这个命令空间,那么推送是不会成功的。
#还有阿里只允许个人创建3个命名空间
#最后一个. 就是指docker build上下文路径,寻找dockerfile和文件中指定相关文件的路径,`.`代表当前目录

🎈推送镜像

docker push registry.cn-shanghai.aliyuncs.com/jacklove/openjdk:8-TZ-CN

🎈jenkins构建新镜像

#前提已经在代码项目根目录放置了jar包的Dockerfile
内容很简单
cat Dockerfile 
FROM registry.cn-shanghai.aliyuncs.com/jacklove/openjdk:8-TZ-CN
#已处理8小时时区,中文显示问题
COPY target/app.jar app.jar
#app.jar没有写工作目录workdir,它会放置在顶部/目录下
EXPOSE 8078
CMD ["java","-jar","app.jar"]

这样配置完成后,jenkins开始构建,就会拉取代码,maven打包,通过在自由风格(没用流水线,后面有时间也会分享下我在学习流水线及实操的文章)构建后,最终成功运行该服务。

🎈验证时区和中文显示

--> # docker exec -it app sh
/ # date
Sun Apr 28 15:57:43 CST 2024

中文展示我们是通过企业微信机器人推送相关信息的。可见原先方块乱码都可以正常显示啦。

image.png

搞定,收工。 祝各位一切顺利。😎