docker镜像验签问题-番外1-alpine配置en_US.UTF-8不生效

背景

一个java应用把镜像从openjdk:8-jdk-alpine切换到openjdk:8u322-jdk-bullseye,在调用第三方http接口里报验签异常。在问ai的过程中发现了一个问题:实际上 en_US.UTF-8 在 Alpine 中不生效,依然是默认 C locale。

复现

以如下一个简单的dockerfile为例。

FROM openjdk:8-jdk-alpine

ENV LANG="en_US.UTF-8"
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /app
COPY /target/user-app.jar /app/user-app.jar
EXPOSE 8003
ENTRYPOINT ["java","-jar","/app/user-app.jar"]

在 Alpine Linux 中,因为它使用 musl libc,并没有 glibc 的 locale 数据库,所以:

  • LANG=en_US.UTF-8 不会加载真正的 en_US UTF-8 locale
  • Alpine 默认依然是 C.UTF-8 或 POSIX locale

可以用以下几种方式验证。

方法 1:查看系统支持的 locale(最直接)

locale -a

预期结果(标准 Alpine):

C
POSIX
C.UTF-8

因此设置 LANG=en_US.UTF-8 根本不会生效。

方法 2:查看 locale 输出

locale

如果 Dockerfile 设置了:

ENV LANG=en_US.UTF-8

可能会看到:

...
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
...

看起来“是生效”,但这只是 环境变量被设置 不代表 locale 存在。
说明只是把环境变量写进容器了,但 并不代表 locale 存在。
实际使用时 musl 会 fallback 到 C.UTF-8。

方法 3:验证排序规则(locale 不生效时影响排序)

执行:

printf "a\nB\n" | sort

如果你在 glibc + en_US.UTF-8,会返回:

a
B

但在 Alpine (C locale),你会得到:

B
a

C locale 排序是 ASCII:大写在前
en_US.UTF-8 排序是语言规则:小写在前

如果在 Alpine 上设置 LANG=en_US.UTF-8 后依然出现这个顺序,就说明 en_US.UTF-8 没有生效。

方法 4:检查本地化库是否存在

运行:

ls /usr/lib/locale

Alpine 标准输出:

ls: /usr/lib/locale: No such file or directory

说明:
默认使用 C.UTF-8(musl 内置 UTF-8 编码的 C locale)

总结验证结果(适用于 Alpine)

Alpine 默认 不支持 en_US.UTF-8 locale

因为:

  • 没有 glibc 的 locale 数据库
  • locale 命令不存在
  • /usr/lib/locale 不存在
  • 排序规则永远是 C 的行为
  • LANG=en_US.UTF-8 只是设置变量,不改变 locale

如果想让 Alpine 真正支持 en_US.UTF-8,需要Alpine + glibc + en_US.UTF-8 locale。

结论:生产环境不要使用alpine镜像。

作者:张三  创建时间:2025-11-28 10:35
最后编辑:张三  更新时间:2025-11-28 11:55