Docker多服务容器启动失败:缺失tzdb.dat引发Java类初始化错误
解决Docker容器中OpenJDK缺失tzdb.dat导致的启动失败问题
问题现象
使用最新镜像启动多服务容器时全部失败,核心报错如下:
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern. 2023-08-04T04:31:26.727100375Z Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class sun.util.calendar.ZoneInfoFile
根源是容器内的OpenJDK缺少时区数据文件:
Caused by: java.lang.Error: java.io.FileNotFoundException: /usr/lib/jvm/java-11-openjdk-11.0.20.0.8-2.el8.x86_64/lib/tzdb.dat (No such file or directory)
针对Docker容器的解决方案
1. 在Dockerfile中安装时区数据包(推荐)
根据容器基础镜像的包管理器,添加tzdata安装步骤:
- RHEL/CentOS 8+ 镜像:
RUN dnf install -y tzdata && \ # 可选:设置时区为你需要的区域,比如上海 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone - Alpine 镜像:
RUN apk add --no-cache tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone
2. 检查并安装完整的OpenJDK包
部分轻量镜像可能只安装了精简版JRE/JDK,导致缺失时区相关文件,换成完整开发包:
# RHEL/CentOS 环境 RUN dnf install -y java-11-openjdk-devel tzdata
3. 应急方案:挂载主机时区文件(不推荐长期使用)
如果无法修改镜像,启动容器时挂载主机的时区文件(注意主机与容器OS需兼容):
docker run -v /usr/share/zoneinfo:/usr/share/zoneinfo -v /etc/localtime:/etc/localtime your-image:latest
关于日志转换符的额外说明
报错中的Unrecognized conversion specifier [d]是附带问题,大概率是log4j2配置文件中使用了错误的日期转换格式(比如误将%d写成[d]),解决完时区文件问题后,可检查日志配置文件,将日期格式修正为标准写法(如%d{yyyy-MM-dd HH:mm:ss})。
内容的提问来源于stack exchange,提问作者sachyy
相关产品推荐
相关产品推荐

