【问题标题】:Unzip not handling utf-8 in Node Alpine Docker image: how to set correct locale?在 Node Alpine Docker 映像中解压缩不处理 utf-8:如何设置正确的语言环境?
【发布时间】:2022-01-20 02:58:12
【问题描述】:

使用this zip file,此节点脚本成功输出文件:

const child_process = require('child_process')
const util = require('util')
const exec = util.promisify(child_process.exec)
exec(`unzip -Z1 metamorpR.zip`).then(zip_contents => {
    if (zip_contents.stderr) {
        throw new Error(`unzip error: ${zip_contents.stderr}`)
    }
    console.log(zip_contents.stdout)
})
metamorpR.z5
Варианты Прохождения.txt
Интерактивная Литература.pdf

但是当我从 Docker 中运行脚本时,它没有。

使用这个 Dockerfile:

FROM node:16-alpine
RUN apk add --no-cache unzip
COPY . .
ENTRYPOINT ["node", "unzip.js"]

构建并运行(替换为您的容器映像名称):

docker build .
docker run --rm 1dc072

输出:

metamorpR.z5
??????? ????????.txt
???????????? ??????????.pdf

我认为这意味着在 Docker 映像中没有正确设置语言环境?任何想法如何解决这个问题?

【问题讨论】:

标签: node.js docker character-encoding locale alpine


【解决方案1】:

如果您指定 -a 开关,显然 Ubuntu 存储库中提供的某些版本的 unzip 可以处理文件名的自动解码。

【讨论】:

  • 文件内容的-a标志不是名称吗?至少在我尝试的时候没有任何区别。
  • 在不知道您使用的解压缩版本的情况下很难验证。尝试 unzip -O cp866 (替换为您的语言环境)Archive.zip 或管道到 iconv 命令 - iconv -f cp1252 -t cp850 我认为它可以在不摆弄语言环境和加倍图像大小的情况下完成
  • @JoelTenta -O CHARSET specify a character encoding for DOS, Windows and OS/2 archives 选项不适用于unzip on alpinedocker run --rm --entrypoint sh alpine:3 -c "apk add unzip && unzip".
【解决方案2】:

TL;DR

unzip on alpine 似乎不支持localesunzip on debian 似乎也不支持 localesunzip on ubuntu 支持使用locales (但没有官方的node ubuntu 图片)。


ubuntu:

FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        locales \
        unzip && \
    apt-get clean
RUN sed -i -e 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/' /etc/locale.gen && \
    locale-gen && \
    update-locale LANG=ru_RU.UTF-8 LC_ALL=ru_RU.UTF-8 && \
    ldconfig
ENV LANG=ru_RU.UTF-8
COPY metamorpR.zip /metamorpR.zip
CMD ["unzip", "-l", "metamorpR.zip"]

...unzip 文件名输出中没有问题:

...但是相同的构建FROM node:16-bullseye 不会产生相同的结果:

您可以在构建期间apply this patch,然后生成语言环境,但是unzip 似乎没有使用locales

FROM node:16-alpine
RUN apk add --no-cache unzip wget
RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-2.34-r0.apk && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-bin-2.34-r0.apk && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-i18n-2.34-r0.apk && \
    apk add glibc-2.34-r0.apk glibc-bin-2.34-r0.apk glibc-i18n-2.34-r0.apk && \
    rm /glibc-2.34-r0.apk /glibc-bin-2.34-r0.apk /glibc-i18n-2.34-r0.apk && \
    /usr/glibc-compat/bin/localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
ENV LANG=ru_RU.UTF-8
COPY metamorpR.zip /metamorpR.zip
CMD ["unzip", "-l", "metamorpR.zip"]

【讨论】:

  • 呃,这真是一团糟。有一个 musl-locales Alpine 包,它可能与您的最终 Dockerfile 大致相同,但它也没有任何效果。我也试过 p7zip,但也没有运气。我可能会尝试使用 npm zip 包,但我想直接使用 unzip,因为当我上次查看时,没有一个 npm zip 包质量很高......
  • 解压缩包在我看来仍然很糟糕。 (有一个看起来不错,直到我遇到已知问题:UTF-8 文件名!)但是将节点安装到 Ubuntu 映像中是有效的。非常感谢!
【解决方案3】:

感谢@masseyb 的回答,我能够让它与这个 Dockerfile 一起工作,它基本上只是手动将 Node 安装到 Ubuntu 映像中。主要缺点是图像大小是两倍,但它相对简单,所以这对我来说是可以接受的缺点。

FROM ubuntu:20.04
RUN apt-get update && \
    apt install -y curl locales unzip && \
    curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
    apt install -y nodejs && \
    rm -rf /var/lib/apt/lists/* && \
    localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.UTF-8
COPY . .
ENTRYPOINT ["node", "unzip.js"]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-17
    • 2017-04-19
    • 2015-11-26
    • 2022-11-13
    • 1970-01-01
    • 2014-01-01
    • 2012-03-21
    • 2013-07-01
    相关资源
    最近更新 更多