全局 NPM 包安装的简单 CircleCI 2.0 配置失败

Simple CircleCI 2.0 configuration fails for global NPM package installation

我有一个可以正常工作的 Docker 文件:

FROM node:10
RUN npm set unsafe-perm true
RUN npm install -g '@oresoftware/r2g@0.0.132'

但是镜像上述 Docker 文件的同一个 CircleCI config.yml 文件不起作用:

{
  "version": 2,
  "jobs": {
    "build": {
      "docker": [
        {
          "image": "circleci/node:10"
        }
      ],
      "steps": [
        {
          "run": "npm set unsafe-perm true"
        },
        {
          "run": "npm install -g --loglevel=warn '@oresoftware/r2g@0.0.132'"
        }
      ]
    }
  }
}

我使用上面的 config.yml 文件在 CircleCI 上得到以下错误:

#!/bin/bash -eo pipefail
npm install -g --loglevel=warn @oresoftware/r2g
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { [Error: EACCES: permission denied, access '/usr/local/lib/node_modules']
npm ERR!   stack:
npm ERR!    'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/circleci/.npm/_logs/2018-06-18T18_26_53_651Z-debug.log
Exited with code 243

CircleCI 2.0 应该使用 Docker,所以我不确定为什么会出现此权限错误。

在 CircleCI 上你需要使用 sudo。默认用户是 circleci,具有无密码 sudo 访问权限。

如前所述,顶部的 Dockerfile 与 CircleCI-config 中的不完全相同。在 Dockerfile 中,基本映像是 node,默认情况下在 root 用户下运行。

另一方面,circleci/node 图像落入非特权 circleci 用户。因此,基于 node 图像的 100% 相同的 Dockerfile 将如下所示:

FROM node:10
RUN useradd -m circleci
USER circleci
RUN npm set unsafe-perm true
RUN npm install -g '@oresoftware/r2g@0.0.132'

对于这个 Dockerfile,会出现与 CircleCI 中相同的错误。

一个解决方案是使用 sudo,问题是你必须在每个使用你安装的节点包的命令上使用 sudo(因为使用 sudo it实际上会安装在 /root 目录中,circleci 用户无法访问该目录)。

我认为更好的选择是将软件包安装在 circleci 主目录中。

{
  "version": 2,
  "jobs": {
    "build": {
      "docker": [
        {
          "image": "circleci/node:10"
        }
      ],
      "steps": [
        {
          "run": "npm set prefix=/home/circleci/npm && echo 'export PATH=$HOME/circleci/npm/bin:$PATH' >> /home/circleci/.bashrc"
        },
        {
          "run": "npm install -g --loglevel=warn '@oresoftware/r2g@0.0.132'"
        }
      ]
    }
  }
}

这样您就不必每次都sudo使用该包。

tldr - 使用以下前缀:

npm install --prefix=$HOME/.local --global serverless
  • serverless 替换为您自己的全局包要求。

背景:

  • 经过一些实验后,上面的方法似乎是我发现的最干净的方法。
  • CircleCI 的当前 circleci/node:lts-buster 图像在路径上有以下内容:

    /home/circleci/.local/bin:/home/circleci/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

  • 由于写入权限被阻止,我无法写入 /home/circleci/bin

  • 我能够写信给 /home/circleci/.local/bin
  • --prefix=$HOME/.local 选项添加到 npm install 命令意味着全局包随后安装到 /home/circleci/.local/bin
  • 安装后,命令,在我的例子中 serverless,是可执行的。

对我有用的是将以下环境变量添加到作业中:

environment:
  NPM_CONFIG_PREFIX: "~/.npm-global"

并一步修改$PATH如下:

steps: 
  - echo 'export PATH=~/.npm-global/bin:$PATH' >> $BASH_ENV
  - npm install
  - npm install -g some-global-package