【问题标题】:No access permission error with npm global install on docker imagedocker image 上的 npm global install 没有访问权限错误
【发布时间】:2017-11-21 20:07:25
【问题描述】:

我正在尝试使用 firebase-tools 和 angular-cli 的全局安装构建一个 docker 映像。 我正在为两个版本的节点构建相同的图像:6.x(LTS 硼)和 v8.x(最新的 alpine)。在本地,两个映像都构建得很好,但是当我尝试在 docker hub 中构建时,只有 v6.x 构建成功。在 v8.x 中,它被困在 未定义和无人用户的访问权限中。我已经在使用 root 用户(USER root),因为没有此设置(或使用 USER 节点),两个图像都无法构建。

这是我的 Dockerfile:

FROM node:latest

USER root

RUN npm install --quiet --no-progress -g @angular/cli@latest firebase-tools
RUN npm cache clean --force

这是输出:

Step 4/5 : RUN npm install --quiet --no-progress -g @angular/cli@latest firebase-tools

 ---> Running in fce3da11b04e

 npm WARN deprecated node-uuid@1.4.8: Use uuid module instead
 /usr/local/bin/firebase -> /usr/local/lib/node_modules/firebase-tools/bin/firebase
 /usr/local/bin/ng -> /usr/local/lib/node_modules/@angular/cli/bin/ng

> node-sass@4.5.3 install /usr/local/lib/node_modules/@angular/cli/node_modules/node-sass
> node scripts/install.js

Unable to save binary /usr/local/lib/node_modules/@angular/cli/node_modules/node-sass/vendor/linux-x64-57 : { Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/@angular/cli/node_modules/node-sass/vendor'
  at Object.fs.mkdirSync (fs.js:890:18)
  at sync (/usr/local/lib/node_modules/@angular/cli/node_modules/mkdirp/index.js:71:13)
  at Function.sync (/usr/local/lib/node_modules/@angular/cli/node_modules/mkdirp/index.js:77:24)
  at checkAndDownloadBinary (/usr/local/lib/node_modules/@angular/cli/node_modules/node-sass/scripts/install.js:111:11)
  at Object.<anonymous> (/usr/local/lib/node_modules/@angular/cli/node_modules/node-sass/scripts/install.js:154:1)
  at Module._compile (module.js:569:30)
  at Object.Module._extensions..js (module.js:580:10)
  at Module.load (module.js:503:32)
  at tryModuleLoad (module.js:466:12)
  at Function.Module._load (module.js:458:3)

errno: -13,
code: 'EACCES',
syscall: 'mkdir',
path: '/usr/local/lib/node_modules/@angular/cli/node_modules/node-sass/vendor' }

> grpc@1.3.8 install /usr/local/lib/node_modules/firebase-tools/node_modules/grpc > node-pre-gyp install --fallback-to-build --library=static_library
node-pre-gyp ERR! Tried to download(undefined): https://storage.googleapis.com/grpc-precompiled-binaries/node/grpc/v1.3.8/node-v57-linux-x64.tar.gz node-pre-gyp ERR! Pre-built binaries not found for grpc@1.3.8 and node@8.1.2 (node-v57 ABI) (falling back to source compile with node-gyp)
gyp WARN EACCES user "undefined" does not have permission to access the dev dir "/root/.node-gyp/8.1.2" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp"
gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp/8.1.2" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp"
gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp/8.1.2" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp"
gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp/8.1.2" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp"
gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp/8.1.2" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/local/lib/node_modules/firebase-tools/node_modules/grpc/.node-gyp"
(infinite loop)

【问题讨论】:

    标签: docker npm


    【解决方案1】:

    我能够通过更改默认的 npm-global 目录来使其正常工作。

    这是我现在的 dockerfile:

    FROM node:latest
    USER node
    
    RUN mkdir /home/node/.npm-global
    ENV PATH=/home/node/.npm-global/bin:$PATH
    ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
    
    RUN npm install --quiet --no-progress -g @angular/cli@latest firebase-tools
    RUN npm cache clean --force
    

    【讨论】:

    • 你应该接受你自己的答案。目前接受的答案建议使用root 并获得太多的赞成票。
    【解决方案2】:

    问题在于,虽然 NPM 以 nobody 用户身份运行全局安装的模块脚本,这很有意义,但最近版本的 NPM 开始将节点模块的文件权限设置为 root。因此,不再允许模块脚本在其模块中创建文件和目录。

    请参阅讨论in NPM issue #3849,以获取一些参考资料。

    一个在 docker 环境中有意义的简单解决方法是将 NPM 默认全局用户设置回root,如下所示:

    npm -g config set user root
    

    在此之后,您不应再有任何EACCES 错误。

    【讨论】:

    • 或者也使用 npm -g config set user $USER 对我有用,因为我真的希望我的用户成为默认用户,而不是 root。
    • @DanieleDellafiore 将全局用户设置为个人用户 ID 没有多大意义。也许您只想使用不带全局 (-g) 标志的 npm
    • 尝试在全球范围内安装cordova-res,但安装成功后无法正常工作。谢谢。
    • 完美运行!
    【解决方案3】:

    使用--unsafe-perm 标志:

    npm install --quiet --no-progress --unsafe-perm -g @angular/cli@latest firebase-tools
    

    我认为这仍然比将npm 用户永久设置为root 更好。 --unsafe-perm 只能用于引起问题的软件包

    【讨论】:

      【解决方案4】:

      我没有强迫 NPM 将包安装到容器中,而是通过映射/引用缺少模块的主机文件夹来绕过这个问题 这也可以防止将来当我用最新版本替换 docker 映像时感到头疼,我不必重复这些阶段来在容器内重新安装缺少的模块:

      我采取的步骤:

      1. 在主机环境中创建一个空文件夹(将用作节点 js 模块的目标)。称之为 node_modules

      2. 在启动运行 docker 容器时使用 --volume 和 --env 开关

      -- 传递的卷将新的主机文件夹(从步骤 1 开始)映射到 docker 内可访问的文件夹

      --env 定义/设置环境变量 NPM_CONFIG_PREFIX 从 docker 内部到我们在步骤 1 中创建的 /node_modules 文件夹

      1. 使用 :

        访问容器

        sudo docker exec -i -t sh

      然后转到 local /node_modules 文件夹正上方的文件夹(这不是我们映射到环境变量的文件夹,而是 docker 映像附带的预先存在的文件夹)

      然后运行命令:

      > npm install -g <mdule-name>
      

      例子

      > npm install -g request
      

      这会将模块安装在我们创建的主机文件夹中。这个模块也可以从 docker 和 host 访问。

      【讨论】:

      • @kaiser 谢谢,只要人们仍然可以看到和使用这些信息......这才是最重要的
      【解决方案5】:

      请勿将用户设置为root 或使用--unsafe-perm

      只需使用node用户,提供当前官方(例如alpine)图片。

      在下方评论Dockerfile

      FROM node:15.5-alpine
      
      # ? Security: do not use the `root` user.
      ENV USER=node
      
      # You can not use `${USER}` here, but reference `/home/node`.
      ENV PATH="/home/node/.npm-global/bin:${PATH}"
      # ? The `--global` install dir
      ENV NPM_CONFIG_PREFIX="/home/node/.npm-global"
      
      # All subsequent commands are run as the `node` user.
      USER "${USER}"
      
      # Pre-create the target dir for global install.
      RUN mkdir -p "${NPM_CONFIG_PREFIX}/lib"
      
      WORKDIR /usr/src/app
      
      COPY package.json package-lock.json ./
      
      # ? Configure NPM, so pkg get installed with correct credentials.
      # Avoids `chmod u+x $DIR` and other workarounds.
      RUN npm --global config set user "${USER}" \
          && npm --global --quiet --no-progress install \
          && npm cache clean --force
      

      @gabriel-araujo 答案的扩展版本。

      您可以通过配置此in the .npmrc file 通过 CLI 标志 (npm --global config set user "${USER}") 替换 setting the user。将user=node 放在项目根.npmrc 文件中,或者直接从Dockerfile 中设置。

      RUN echo "user=node" > "${NPM_CONFIG_PREFIX}/etc/.npmrc"
      

      如果您使用docker-compose.yml,您可以将其添加为environment: - … 变量。

      希望能帮助您在某处运行更安全的 NodeJS 容器并提取一些很棒的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-08
        • 2018-06-08
        • 1970-01-01
        • 2022-11-14
        • 1970-01-01
        • 2019-08-21
        • 1970-01-01
        • 2022-11-16
        相关资源
        最近更新 更多