使用docker过程当中遇过的最诡异的问题,服务在本地环境中,经过在IDEA里面运行,或者使用java -jar ***.war运行,获取验证码图片都没有问题,可是运行在docker中,图片正常返回,可是上面的汉字却没法显示。java
(正常返回)docker
(非正常返回)bash
将汉字写入图片的代码如:app
private String drawRandomNum(Graphics2D g) { StringBuffer sb = new StringBuffer(); // 设置颜色 g.setColor(Color.YELLOW); // 设置字体 g.setFont(new Font("宋体", Font.ITALIC, 20)); // 准备经常使用汉字集 String base = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765"; int x = 5; // 控制字数 for (int i = 0; i < 4; i++) { // 设置字体旋转角度 int degree = new Random().nextInt() % 30; // 截取汉字 String ch = base.charAt(new Random().nextInt(base.length())) + ""; sb.append(ch); // 正向角度 g.rotate(degree * Math.PI / 180, x, 20); g.drawString(ch, x, 20); // 反向角度 g.rotate(-degree * Math.PI / 180, x, 20); x += 30; } System.out.println(sb.toString()); return sb.toString(); }
基本逻辑是从unicode编码的汉字字符集中随机抽取4个汉字,调用Graphics2D的drawString方法画入。dom
排查问题的第一步,将汉字字符集转化为英语字符集,方法调用没有问题,英语字母能够正常显示,问题彷佛落在docker环境对中文字符的支持上。maven
经过参考,对container中locale进行检查和重置(修改container中locale的方法):字体
C.UTF-8原本就已经支持中文,因此问题也不在locale。编码
由于代码中使用了Graphics2D进行画图,试着用关键字”Graphics2D 画汉字 docker 乱码“百度一下,果真搜出了好东西。.net
问题的根源在于:container环境中缺少对中文字体的支持,须要添加字体文件simsun.ttf 到/usr/share/fonts中,具体步骤如:3d
1)进入container:
docker exec -it 40ebba024c0b bash
2)打开/usr/share/fonts:
cd /usr/share/fonts
3)下载字体文件:
wget https://dlc2.pconline.com.cn/filedown_367689_7048847/3BswZ0YQ/simsun.zip
结果如:
4)解压simsun.zip:
unzip simsun.zip
结果如:
5)拷贝一份simsun.ttf,并重命名为simsun.tt
cp simsun.ttf simsun.tt
6)退出并重启container:
问题解决!!
结论:Docker环境和本地环境是存在差别的,在解决具体问题的过程当中,须要将这种差别添加到打包的过程当中,如本例中须要将字体文件进行拷贝,能够在Dockerfile中添加
COPY simsun.ttf /usr/share/fonts/simsun.tt
(因为使用了docker-maven-plugin进行打包,这一步并未实践)