docker-lambda icon indicating copy to clipboard operation
docker-lambda copied to clipboard

Permissions problems with NPM on build-nodejs6.10

Open alixaxel opened this issue 7 years ago • 2 comments

I have the following file structure:

.
├── build
│   ├── index.js
│   ├── node_modules
│   └── package.json
├── Makefile
├── node_modules
│   ├── ...
├── package.json
├── package-lock.json
└── source
    └── index.js

The top-level node_modules and source contain code that executes on my machine, but not on Lambda.

To package the code to Lambda, I'm relying on the following make script:

build: node_modules
  npm install @alix/aws
  rm --force --recursive build/
  node_modules/.bin/babel --copy-files --out-dir build source/
  cp package.json build/
  sed --in-place 's~/modules/@alix/~/../modules/@alix/~' build/package.json
  docker run \
    --rm \
    --user $$(id -u "$$USER"):$$(id -g "$$USER") \
    --volume "$$PWD":/var/task/apis/api \
    --volume "$$PWD/../../modules":/var/task/modules \
    --workdir /var/task/apis/api node:6.10.3 \
  npm install --no-optional --no-shrinkwrap --prefix build/ --production
  rmdir build/etc/
  node-prune build/

node_modules:
  npm install

This works fine, and even node-gyp packages are compatible with Lambda, but for consistency reasons with other runtime Lambdas I would like to use the lambci/lambda:build-nodejs6.10 Docker image instead of node:6.10.3. However, when I do, I ran into a couple of permission related problems:

$ make build
npm install @alix/aws
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":
"linux","arch":"x64"})

+ @alix/[email protected]
updated 1 package in 3.803s
rm --force --recursive build/
node_modules/.bin/babel --copy-files --out-dir build source/
source/index.js -> build/index.js
cp package.json build/
sed --in-place 's~/modules/@alix/~/../modules/@alix/~' build/package.json
docker run \
  --rm \
  --user $(id -u "$USER"):$(id -g "$USER") \
  --volume "$PWD":/var/task/apis/api \
  --volume "$PWD/../../modules":/var/task/modules \
  --workdir /var/task/apis/api lambci/lambda:build-nodejs6.10 \
npm install --no-optional --no-shrinkwrap --prefix build/ --production
npm ERR! addLocal Could not install /var/task/modules/@alix/aws
npm ERR! Linux 4.10.0-42-generic
npm ERR! argv "/var/lang/bin/node" "/var/lang/bin/npm" "install" "--no-optional" "--no-shrinkwrap" "--prefix" "build/" "--production"
npm ERR! node v6.10.3
npm ERR! npm  v3.10.10
npm ERR! path /.npm
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall mkdir

npm ERR! Error: EACCES: permission denied, mkdir '/.npm'
npm ERR!     at Error (native)
npm ERR!  { Error: EACCES: permission denied, mkdir '/.npm'
npm ERR!     at Error (native)
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/.npm',
npm ERR!   parent: 'api' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

npm ERR! Please include the following file with any support request:
npm ERR!     /var/task/apis/api/npm-debug.log
Makefile:4: recipe for target 'build' failed
make: *** [build] Error 243

If I remove the --user parameter, it works but I lose write-access to build.

I also tried to mount a new volume on --volume /tmp:/.npm, and that seems to solve the problem, but it's polluting my host /tmp directory. Setting the environment variable HOME to trick NPM also works but again, it's polluting some other directory...

Is there a simple solution that I am missing?

alixaxel avatar Dec 29 '17 23:12 alixaxel

There's too much going on here for me to understand what you're doing – probably easiest to just boil it down to a one-liner. Try using an interactive bash session on the build image to debug.

mhart avatar Dec 30 '17 00:12 mhart

@mhart Essentially, I have a perfectly normal ./build/ackage.json that looks like this:

{
  "name": "api",
  "version": "0.0.1",
  "description": "API",
  "main": "build/index.js",
  "scripts": {
    "build": "make build"
  },
  "author": "Alix Axel",
  "license": "UNLICENSED",
  "dependencies": {
    "claudia-api-builder": "^2.5.1",
    "lodash": "^4.17.4",
    "tldjs": "^2.2.0"
  },
  "optionalDependencies": {
    "aws-sdk": "^2.123.0"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.0"
  }
}

Outside of the build directory I execute NPM install from within the Docker container:

docker run \
  --rm \
  --user 1000:1000 \ # this is the same UID:GID of the host user
  --volume "$PWD":/var/task/apis/api \
  --workdir /var/task/apis/api lambci/lambda:build-nodejs6.10 \
npm install --no-optional --no-shrinkwrap --prefix build/ --production

With lambci/lambda:build-nodejs6.10 it fails with the error above but with node:6.10.3 it works fine.

alixaxel avatar Dec 30 '17 01:12 alixaxel