【问题标题】:Install nodejs and npm in Dockerfile在 Dockerfile 中安装 nodejs 和 npm
【发布时间】:2020-06-11 21:59:28
【问题描述】:

上下文

我有一个 Dockerfile 来创建一个包含 apache 网络服务器的图像。但是,我还想使用 Dockerfile 构建我的网站,以便构建过程不依赖于开发人员的本地环境。请注意,docker 容器仅用于本地开发而非生产。

问题

我有这个 Dockerfile:

FROM httpd
RUN apt-get update -yq
RUN apt-get -yq install curl gnupg
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash
RUN apt-get update -yq
RUN apt-get install -yq \
        dh-autoreconf=19 \
        ruby=1:2.5.* \
        ruby-dev=1:2.5.* \
        nodejs

我建造它:

sudo docker build --no-cache .

构建成功完成,以下是部分输出:

Step 9/15 : RUN curl -sL https://deb.nodesource.com/setup_12.x | bash
 ---> Running in e6c747221ac0
......
......
......
Removing intermediate container 5a07dd0b1e01
 ---> 6279003c1e80
Successfully built 6279003c1e80

但是,当我使用这个在容器中运行图像时:

sudo docker container run --rm -it --name=debug 6279003c1e80 /bin/bash

然后在容器内执行apt-cache policy 时,它不会显示应该使用 curl 命令添加的存储库。同样在执行apt-cache policy nodejs 时,它显示已安装旧版本。

但是,当我在容器内运行以下命令时:

curl -sL https://deb.nodesource.com/setup_12.x | bash
apt-cache policy
apt-cache policy nodejs

它显示存储库已添加,并显示更新的 nodejs 版本可用。

那么为什么当使用 curl 命令在 docker 文件中使用 RUN 时它似乎不起作用,但是当从 shell 在容器中手动执行它时它确实起作用?我该如何解决这个问题?

更新

  • 请注意,为了防止出现缓存问题,我使用了 --no-cache 标志。
  • 我还删除了所有容器并执行了sudo docker system prune 并重建了映像,但没有成功。
  • 我尝试按照用户“hmm”的建议将所有内容捆绑在一个 RUN 命令中(因为这是 apt 命令的最佳做法):
RUN apt-get update -yq \
    && apt-get -yq install curl gnupg && \
    && curl -sL https://deb.nodesource.com/setup_12.x | bash \
    && apt-get update -yq \
    && apt-get install -yq \
        dh-autoreconf=19 \
        ruby=1:2.5.* \
        ruby-dev=1:2.5.* \
        nodejs \
    && rm -rf /var/lib/apt/lists/*

【问题讨论】:

    标签: node.js docker npm


    【解决方案1】:

    您可能会遇到缓存层的问题。在 Dockerfile 最佳实践文档中有一个 long section 关于使用 apt-get。可能值得一读。

    要点是 Docker 不识别第一个和第二个RUN apt-get update 之间的任何区别,也不知道apt-get install 依赖于一个新的apt-get update 层。

    解决方案是将所有这些组合成一个 RUN 命令(推荐)或在构建过程中禁用缓存 (docker build --no-cache)。

    RUN apt-get update -yq \
        && apt-get -yq install curl gnupg ca-certificates \
        && curl -L https://deb.nodesource.com/setup_12.x | bash \
        && apt-get update -yq \
        && apt-get install -yq \
            dh-autoreconf=19 \
            ruby=1:2.5.* \
            ruby-dev=1:2.5.* \
            nodejs
    

    编辑: 在本地运行 Dockerfile,我注意到 curl 命令没有输出。删除 -s 标志(静默失败)后,您可以看到它由于无法验证服务器的 SSL 证书而失败:

    curl: (60) SSL certificate problem: unable to get local issuer certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
    curl failed to verify the legitimacy of the server and therefore could not
    establish a secure connection to it. To learn more about this situation and
    how to fix it, please visit the web page mentioned above.
    

    那个问题的解决方案是在运行curl 之前安装ca-certificates。我已经更新了上面的RUN 命令。

    【讨论】:

    • 感谢您的链接,我会看看!我不认为缓存是问题,因为我已经在使用 --no-cache 标志。我什至尝试不使用 docker-compose 所以使用:sudo docker build --no-cache . 但这仍然给我同样的问题。在一个 RUN 语句中运行它之后,我仍然安装了旧的节点版本并且没有添加 repo。
    • @Stefan 对不起,我错过了你已经在使用--no-cache。请参阅我的编辑以获取潜在的解决方案。
    • 非常感谢!我没有意识到我正在使输出静音,我认为它正在成功执行。我不明白为什么有时 docker build 在出现错误时会失败(例如使用未安装的 shell 命令时),而其他时候它会愉快地继续。还是因为我在 curl 命令中使用了-s
    • -s 隐藏了错误输出,但 Docker 之所以继续是因为curl https://<url> | bash 命令的退出状态实际上是bash 的退出状态(本例中为0)。要导致管道由于 curl 的非零退出状态而失败,您需要将默认 shell 调整为例如bash 并使用 set -o pipefail: SHELL ["/bin/bash", "-o", "pipefail", "-c"].
    猜你喜欢
    • 1970-01-01
    • 2018-03-10
    • 2017-02-20
    • 2018-11-14
    • 2023-03-24
    • 1970-01-01
    • 2015-02-01
    • 2017-08-02
    • 2019-06-25
    相关资源
    最近更新 更多