docker-node: fails to invoke npm when used in run-scripts
Environment
- Platform: MacOS
- Docker Version: 20.10.16
- Node.js Version: 16.15.1
- Image Tag: node:16.15.1-alpine
Expected Behavior
Given the following package.json
{
"name": "test",
"scripts": {
"ver": "npm --version"
},
"devDependencies": {
"cowsay": "^1.5.0"
}
}
$ npm run ver
> ver
> npm --version
8.12.1
The same behavior should be replicated within a container runtime
Current Behavior
When running within a container runtime, npm
fails and returns 243 exit code
$ docker run --rm -v $PWD:/app --workdir /app --entrypoint npm node:16.15.1-alpine run ver
> ver
> npm --version
npm notice
npm notice New minor version of npm available! 8.11.0 -> 8.12.1
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.12.1>
npm notice Run `npm install -g npm@8.12.1` to update!
npm notice
$ echo $?
243
When using a different image, it works as expected
$ docker run --rm -v $PWD:/app --workdir /app --entrypoint npm node:14-alpine run ver
> test@ ver /app
> npm --version
6.14.17
It works on on some images (note the --user node:node
option)
$ docker run --rm -v $PWD:/app --workdir /app --entrypoint npm node:16.15.0-alpine3.15@sha256:bb776153f81d6e931211e3cadd7eef92c811e7086993b685d1f40242d486b9bb run ver
> ver
> npm --version
8.5.5
npm notice
npm notice New minor version of npm available! 8.5.5 -> 8.12.1
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.12.1>
npm notice Run `npm install -g npm@8.12.1` to update!
npm notice
$ docker run --rm -v $PWD:/app --workdir /app --entrypoint npm --user node:node node:18-alpine run ver
> ver
> npm --version
8.11.0
when the node
user is used, then there a permission issue when mount volumes are used.
$ docker run --rm -it -v $PWD:/src -v node_modules:/src/node_modules --workdir /src --user node:node --entrypoint /bin/sh node:lts-alpine -c 'npm install && npm run ver'
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /src/node_modules/ansi-regex
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/src/node_modules/ansi-regex'
npm ERR! [Error: EACCES: permission denied, mkdir '/src/node_modules/ansi-regex'] {
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'mkdir',
npm ERR! path: '/src/node_modules/ansi-regex'
npm ERR! }
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.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/node/.npm/_logs/2022-06-09T07_10_27_665Z-debug-0.log
$ docker run --rm -it -v $PWD:/src -v node_modules:/src/node_modules --workdir /src --user root:root --entrypoint /bin/sh node:lts-alpine -c 'npm install && npm run ver'
added 41 packages, and audited 42 packages in 2s
3 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 8.11.0 -> 8.12.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.12.1
npm notice Run npm install -g npm@8.12.1 to update!
npm notice
> ver
> npm --version
Steps to Reproduce
Use the package.json
configuration above and repeat the commands in this post.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 40
- Comments: 32 (1 by maintainers)
Commits related to this issue
- Hardcode node version to 16.15.0 in tests There seems to be an issue with version 16.15.1 which causes the npm install and npm scripts to exit with code 243 in some circumstances (https://github.com/... — committed to 7digital/mysql2-timeout by scooper91 2 years ago
- Temporary fix for https://github.com/nodejs/docker-node/issues/1734 — committed to ideal-postcodes/postcodes.io by cblanc 2 years ago
- Temporary fix for https://github.com/nodejs/docker-node/issues/1734 — committed to ideal-postcodes/postcodes.io by cblanc 2 years ago
- Fix error 243 in GitHub Actions Caused by latest node lts? Pinning the version fixes the error. Ref: https://github.com/nodejs/docker-node/issues/1734 — committed to kdeloach/kdeloach.github.io by kdeloach 2 years ago
Probably the same problem with docker image of 18.2-alpine, npm version 8.9.0.
The issue here seems npm doesnt want to run as
root
. Example when container is run asroot
and when switched to usernode
usingsu
:Running the container as
node
fixes the issue.The simple solution is to change the nodejs version. I was facing the same issue, i fixed it by changing node version from 16 to 14 and this worked
we are facing the same issue.
on k8s we’re setting the pod security context to run with an arbitrary user id, after deleting this in the config the pod starts again.
we are setting the tag / sha of images to node:16.14 for now, to keep our pod settings.
also see https://github.com/npm/cli/issues/4996
@foolioo NPM overrides uid if current user is root in the following line.
https://github.com/npm/cli/blob/9f94049f058687b916da726ea625b5fa68d0829d/node_modules/%40npmcli/promise-spawn/lib/index.js#L13
This was removed before, but reintroduced now.
npm/promise-spawn#6
Actually, this is not only an issue with run-scripts. node:16-alpine docker image is completely broken as a base build image in these cases:
readOnlyRootFilesystem: true
.The source of these issues is that
npm_config_prefix
is set to/usr/local
andnpm_config_userconfig
is not set at all, so NPM is trying to use HOME folder which in the docker image is set to/
. Again, that folder is not writable by any of the users except root, but remember, NPM ignores root user due to https://github.com/npm/cli/blob/37bf6d31bd2f68e661928744833b57dcabbb0d1a/node_modules/@npmcli/promise-spawn/lib/index.js#L13The only way I found to fix this on Jenkins is set
NPM_CONFIG_CACHE
to something like/tmp/jenkins/.npm
. GitLab/GitHub runners can be fixed in similar manner.I guess the final fix should be to create .npm cache folder somewhere writable by any user on the docker image, so at least it works by default on CI pipelines. Maybe create some kind of documented folder specified via
npm_config_userconfig
so anyone can map it and modify the behaviour of a running user.P.S. Why NPM tries to spawn a process according to permission on current folder in case it is run by the root user is still a mistery to me. It goes against all commons. Programs should not modify running user.
In my case, I use a docker-compose.yml as is:
And I had this “243” error (which a few months ago with the exact same docker-compose setup I hadn’t).
First I tried to upgrade to node 18, but the error was the same. Then I tried to specify the group of the user from “node” to “node:node”. Same error.
Then I remembered sometimes on my local there would be an error about writing on the “.npm” folder because of lack of permissions. So I figured I’d had the volume so the npm script would not have to write it on the host folder system (the one on Github must have reduced folder permissions for security purposes).
Then the CI on Github started to be more eloquent, this time it would not manage to write a log file on the “.npm/_logs” folder. Getting close:
So I decided to also create the “_logs” folder on my “docker-data/npm” folder, so the npm script would not have to create the folder as well. Here is my folder structure:
And I also had to remove the “user: node:node” by the way (not sure if I put it back it will still work):
With this setup, running this command will work without 243 errors
As well as installing dependencies:
But compiling my assets will fail (this uses Laravel Mix behind the scene)
Edit
I managed to fix all permission issues by starting from Ubuntu:22.04 instead of Node:18-alpine on my Dockerfile
I recap for folks that want to do the same
docker-compose.yml
docker/node/18/Dockerfile
Now all theses commands on my CI works without perm issues
@scooper91 I know, but unfortunately it doesn’t fit my use case.
For me, problems disappear when I add
USER node
command before invoking mynpm run ...
command inside my Dockerfile.Example:
@SmallhillCZ
Not fully correct. It depends whether you are using the container in conjunction with mount/data volumes as
node_modules
directory. When it is used, the user must beroot
in most cases (depends on the inner implementation of how mount volumes work across different operating systems)I’m having a similar issue. We’re seeing it when we try to do an
npm install
from the Docker command, when we set the user for the container. If you set the node cache to a non-existent path, it seems to work.Can replicate it using a simple
package.json
file with a dependency. This example assumes thepackage.json
is owned by user 1001.When setting
--cache=nope
, the install works:EDIT:
It appears (at least in part) to do with the home directory for the user it’s running as. Running as user 1001 (which doesn’t exist in the container) fails to run
npm
at all:If you add the user with that ID, it creates the home directory and works:
If you add the user with that ID, but without the home directory, you get the same error:
For us this was specifically with the
16.15.1
patch release,16.15.0
works in our case.Seeing the same issue in my Jenkins pipeline with
node:16.15-alpine3.15
. I cannot reproduce the issue locally though.@yuki-js Have you tried adding a user to match the mounted file permissions, and using that to use
npm
? Obviously it isn’t ideal, but it worked for our use case. (See my comment above). Can see how it works with our setup here: https://github.com/7digital/mysql2-timeout/blob/dbc820bcdd7a638e1f02bf983beb6bb52059d07f/docker-compose.yml#L12Also seeing this issue, hard coding to
node:16.15.0-alpine
in the meantime.