Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node:7.9-alpine unable to build package due python is not installed #384

Closed
rwillians opened this issue Apr 19, 2017 · 45 comments
Closed

node:7.9-alpine unable to build package due python is not installed #384

rwillians opened this issue Apr 19, 2017 · 45 comments
Labels

Comments

@rwillians
Copy link

rwillians commented Apr 19, 2017

Latest solution #384 (comment)


Edit 2017: check this solution #384 (comment)
Edit 2021: check this solution #384 (comment)
Edit 2021: check note on required dependencies: #384 (comment) and #384 (comment)
Edit 2022: the package python seems to have been deprecated/dropped a while ago in favor of python2 and python3, checkout this updated snippet #384 (comment)


Recently I tried to dockerize a project which uses the bcrypt package. Everything works just fine on my mac but when I run it on Docker yarn throws a lot of errors related to gyp when trying to build the package during the installation process.

Here's my Dockerfile:

FROM node:7.9-alpine
MAINTAINER Rafael Willians <me@rwillians.com>

RUN mkdir -p /usr/src/auth-service
WORKDIR /usr/src/auth-service

COPY package.json .
RUN yarn --no-emoji --prod

COPY . .

EXPOSE 3000

Here's the output log:

$ docker-compose up --build
Building api
Step 1/8 : FROM node:7.9-alpine
 ---> 5e1532cfe1ea
Step 2/8 : MAINTAINER Rafael Willians <me@rwillians.com>
 ---> Using cache
 ---> 08fe67f74ce1
Step 3/8 : RUN mkdir -p /usr/src/auth-service
 ---> Using cache
 ---> df72f45a471a
Step 4/8 : WORKDIR /usr/src/auth-service
 ---> Using cache
 ---> 6ef48543f07e
Step 5/8 : COPY package.json .
 ---> Using cache
 ---> b8d993552d26
Step 6/8 : RUN yarn --no-emoji --prod
 ---> Running in c7927c31e1ce
yarn install v0.22.0
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
error /usr/src/auth-service/node_modules/bcrypt: Command failed.
Exit code: 1
Command: sh
Arguments: -c node-pre-gyp install --fallback-to-build
Directory: /usr/src/auth-service/node_modules/bcrypt
Output:
node-pre-gyp info it worked if it ends with ok
node-pre-gyp verb cli [ '/usr/local/bin/node',
node-pre-gyp verb cli   '/usr/src/auth-service/node_modules/bcrypt/node_modules/.bin/node-pre-gyp',
node-pre-gyp verb cli   'install',
node-pre-gyp verb cli   '--fallback-to-build' ]
node-pre-gyp info using node-pre-gyp@0.6.32
node-pre-gyp info using node@7.9.0 | linux | x64
node-pre-gyp verb command install []
node-pre-gyp info check checked for "/usr/src/auth-service/node_modules/bcrypt/lib/binding/bcrypt_lib.node" (not found)
node-pre-gyp http GET https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.2/bcrypt_lib-v1.0.2-node-v51-linux-x64.tar.gz
node-pre-gyp http 404 https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.2/bcrypt_lib-v1.0.2-node-v51-linux-x64.tar.gz
node-pre-gyp ERR! Tried to download(404): https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.2/bcrypt_lib-v1.0.2-node-v51-linux-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for bcrypt@1.0.2 and node@7.9.0 (node-v51 ABI) (falling back to source compile with node-gyp)
node-pre-gyp http 404 status code downloading tarball https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.2/bcrypt_lib-v1.0.2-node-v51-linux-x64.tar.gz
node-pre-gyp verb command build [ 'rebuild' ]
gyp info it worked if it ends with ok
gyp verb cli [ '/usr/local/bin/node',
gyp verb cli   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js',
gyp verb cli   'clean' ]
gyp info using node-gyp@3.5.0
gyp info using node@7.9.0 | linux | x64
gyp verb command clean []
gyp verb clean removing "build" directory
gyp info ok
gyp info it worked if it ends with ok
gyp verb cli [ '/usr/local/bin/node',
gyp verb cli   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js',
gyp verb cli   'configure',
gyp verb cli   '--fallback-to-build',
gyp verb cli   '--module=/usr/src/auth-service/node_modules/bcrypt/lib/binding/bcrypt_lib.node',
gyp verb cli   '--module_name=bcrypt_lib',
gyp verb cli   '--module_path=/usr/src/auth-service/node_modules/bcrypt/lib/binding' ]
gyp info using node-gyp@3.5.0
gyp info using node@7.9.0 | linux | x64
gyp verb command configure []
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb `which` failed Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/usr/local/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/index.js:44:5
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/access.js:8:5
gyp verb `which` failed     at FSReqWrap.oncomplete (fs.js:114:15)
gyp verb `which` failed  python2 { Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/usr/local/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/index.js:44:5
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/access.js:8:5
gyp verb `which` failed     at FSReqWrap.oncomplete (fs.js:114:15) code: 'ENOENT' }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` failed Error: not found: python
gyp verb `which` failed     at getNotFoundError (/usr/local/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/index.js:44:5
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/access.js:8:5
gyp verb `which` failed     at FSReqWrap.oncomplete (fs.js:114:15)
gyp verb `which` failed  python { Error: not found: python
gyp verb `which` failed     at getNotFoundError (/usr/local/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/index.js:44:5
gyp verb `which` failed     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/access.js:8:5
gyp verb `which` failed     at FSReqWrap.oncomplete (fs.js:114:15) code: 'ENOENT' }
gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack     at PythonFinder.failNoPython (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:454:19)
gyp ERR! stack     at PythonFinder.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:368:16)
gyp ERR! stack     at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:68:16)
gyp ERR! stack     at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp ERR! stack     at /usr/local/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp ERR! stack     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/index.js:44:5
gyp ERR! stack     at /usr/local/lib/node_modules/npm/node_modules/which/node_modules/isexe/access.js:8:5
gyp ERR! stack     at FSReqWrap.oncomplete (fs.js:114:15)
gyp ERR! System Linux 4.9.13-moby
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "--fallback-to-build" "--module=/usr/src/auth-service/node_modules/bcrypt/lib/binding/bcrypt_lib.node" "--module_name=bcrypt_lib" "--module_path=/usr/src/auth-service/node_modules/bcrypt/lib/binding"
gyp ERR! cwd /usr/src/auth-service/node_modules/bcrypt
gyp ERR! node -v v7.9.0
gyp ERR! node-gyp -v v3.5.0
gyp ERR! not ok
node-pre-gyp ERR! build error
node-pre-gyp ERR! stack Error: Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/usr/src/auth-service/node_modules/bcrypt/lib/binding/bcrypt_lib.node --module_name=bcrypt_lib --module_path=/usr/src/auth-service/node_modules/bcrypt/lib/binding' (1)
node-pre-gyp ERR! stack     at ChildProcess.<anonymous> (/usr/src/auth-service/node_modules/node-pre-gyp/lib/util/compile.js:83:29)
node-pre-gyp ERR! stack     at emitTwo (events.js:106:13)
node-pre-gyp ERR! stack     at ChildProcess.emit (events.js:194:7)
node-pre-gyp ERR! stack     at maybeClose (internal/child_process.js:899:16)
node-pre-gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
node-pre-gyp ERR! System Linux 4.9.13-moby
node-pre-gyp ERR! command "/usr/local/bin/node" "/usr/src/auth-service/node_modules/bcrypt/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /usr/src/auth-service/node_modules/bcrypt
node-pre-gyp ERR! node -v v7.9.0
node-pre-gyp ERR! node-pre-gyp -v v0.6.32
node-pre-gyp ERR! not ok
Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/usr/src/auth-service/node_modules/bcrypt/lib/binding/bcrypt_lib.node --module_name=bcrypt_lib --module_path=/usr/src/auth-service/node_modules/bcrypt/lib/binding' (1)
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
ERROR: Service 'api' failed to build: The command '/bin/sh -c yarn --no-emoji' returned a non-zero code: 1

I have opened this issue here because the error log mentioned that python wasn't found in the PATH so this is probably some error in node's 7.9-alpine Dockerfile, right?

I also ran sh against the built image and checked by myself that there was no python or python2 installed.

Not sure if those information are enough, I'm kinda new to Docker and Node. Please let me know if I should provide more information.

I got stuck here using node:15.1.0-alpine3.12 Continual fail until I replaced python with python3.
Where?

@rwillians rwillians changed the title node:7.9-alpine python is not been installed node:7.9-alpine unable to build package due python is not installed Apr 19, 2017
@LaurentGoderre
Copy link
Member

The point of the alpine image is to be as small as possible so it doesn't include python. See #282 on how to do it.

@rwillians
Copy link
Author

@LaurentGoderre thanks for the help!

I thought it was a problem in the node:7.9-alpine image since I saw that python was been installed, but in further reading I've learned that python was only been installed temporarily.

@LaurentGoderre
Copy link
Member

Note that a new feature is coming to docker, the ability to have different build and run image which would solve this issue.

@jephir
Copy link

jephir commented Apr 21, 2017

I believe this is moby/moby#7115 for anyone else who was looking for it.

@JamesKyburz
Copy link

@rwillians I have solved building native modules on alpine by adding the following to the Dockerfile

run apk --no-cache add --virtual native-deps \
  g++ gcc libgcc libstdc++ linux-headers make python && \
  npm install --quiet node-gyp -g &&\
  npm install --quiet && \
  apk del native-deps

This way the image size is not affected because it's all in one layer.

Thanks @LaurentGoderre will look out for that!

@rwillians
Copy link
Author

Thanks for sharing @JamesKyburz

@SimenB
Copy link
Member

SimenB commented Jul 7, 2017

This can be closed, right?

We could probably put some caveats in the readme about using the alpine image, as well as some examples for using multi-stage builds.

@rwillians
Copy link
Author

@SimenB can be closed.

I think that would be of a great help to docker/node newcomers, like me

@daniel94104
Copy link

My container still cannot find python2 in PATH even though I added the command mentioned above

@rwillians
Copy link
Author

rwillians commented Jul 28, 2017 via email

@daniel94104
Copy link

@rwillians Thanks you so much!

@omeid
Copy link

omeid commented Aug 14, 2017

The point of the alpine image is to be as small as possible.

While that is true, it is also important to consider that it is node:*-alpine, and node-gyp fairly standard and used in many common packages like libsass, libpq, and many more. I think a couple of mb added to node alpine would be a very small cost for making majority of project just work.

@SimenB
Copy link
Member

SimenB commented Aug 14, 2017

I think a couple of mb added to node alpine would be a very small cost for making majority of project just work.

I disagree that we should add anything to the alpine image other than node, npm and yarn. But we should document that fact so it's obvious to users.

We have some text about this fact in the readme.

To minimize image size, it's uncommon for additional related tools (such as git or bash) to be included in Alpine-based images. Using this image as a base, add the things you need in your own Dockerfile (see the alpine image description for examples of how to install packages if you are unfamiliar).

https://github.com/nodejs/docker-node/blob/master/README.md#nodealpine

Maybe just mention python and/or native dependencies as well? PR welcome!

@omeid
Copy link

omeid commented Aug 14, 2017

I am struggling to see how having both npm and yarn is acceptable while node-gyp is out of question?

@SimenB
Copy link
Member

SimenB commented Aug 14, 2017

node-gyp is included (npm bundles it). It's not on $PATH, but I think both node and yarn adds it to $PATH if it invokes it during lifecycle stages, so if it's used in build scripts you're good to go.

docker run node:8-alpine /usr/local/lib/node_modules/npm/bin/node-gyp-bin/node-gyp

I also see that you just mentioned node-gyp. I was hung up in python, which the issue was originally about. Sorry about the confusion!

@omeid
Copy link

omeid commented Aug 14, 2017

Ah, that makes sense. Thanks for the clarification.

@Macmee
Copy link

Macmee commented Dec 20, 2017

I fixed the issue by adding these lines to my docker file

RUN apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python
RUN npm install --quiet node-gyp -g

@rwillians
Copy link
Author

@Macmee I suggest you to use JamesKyburz's solution #384 (comment) in order to keep your image minimal.

@caroso1222
Copy link

In case it helps anyone, I had to install a bunch of other apk dependencies - apart from those suggested at #384 (comment) - given that I still depend on some bower packages. I do clean the virtual dependencies after the npm install to keep my image minimal. This is how my Dockerfile looks like:

RUN apk --no-cache add --virtual native-deps \
  g++ gcc libgcc libstdc++ linux-headers autoconf automake make nasm python git && \
  npm install --quiet node-gyp -g

WORKDIR /usr/src/app

COPY package*.json bower.json .bowerrc ./

RUN npm set progress=false && \
  npm i --silent && \
  $(npm bin)/bower --allow-root i

RUN apk del native-deps

@euclid1990
Copy link

Worked ! Thanks

@brickolicious
Copy link

Nailed it, thanks

@LaurentGoderre
Copy link
Member

I recommend #384 (comment) to keep your image size smaller.

@tonypee
Copy link

tonypee commented Apr 18, 2019

This means that building the docker image now takes a long time (downloading, building g++, make, python). And --no-cache is required to keep the bundle size down

is there any good way around this? Does anyone else see this as an issue?

@JamesKyburz
Copy link

@tonypee Yes this seems to be a common issue, every time package.json is changed all build dependencies need to be installed again. This is because it is often on the same docker layer.

I got around this issue using multi stage builds. Here is an example Dockerfile

The dependencies aren't in the same layer as package.json avoiding this issue. Also because it uses multi stage builds the size of the image isn't affected :)

FROM jameskyburz/node:10.15.3-alpine-devtools as devtools

LABEL maintainer="James Kyburz james.kyburz@gmail.com"

WORKDIR /usr/src/app

ENV NPM_CONFIG_LOGLEVEL warn
ARG NODE_ENV=development
COPY package.json package-lock*.json npm-shrinkwrap*.json /usr/src/app/
RUN \
  npm i && \
  npm rebuild bcrypt --build-from-source

FROM node:10.15.3-alpine

WORKDIR /usr/src/app

COPY . /usr/src/app
COPY --from=devtools /usr/src/app/node_modules /usr/src/app/node_modules

USER node

ENTRYPOINT ["node", "src/index"]
CMD []

EXPOSE 5000

@mayeaux
Copy link

mayeaux commented Jan 6, 2020

(1/17) Purging native-deps (20200106.014645)
(2/17) Purging g++ (9.2.0-r3)
(3/17) Purging libc-dev (0.7.2-r0)
(4/17) Purging musl-dev (1.1.24-r0)
(5/17) Purging gcc (9.2.0-r3)
(6/17) Purging binutils (2.33.1-r0)
(7/17) Purging libatomic (9.2.0-r3)
(8/17) Purging libgomp (9.2.0-r3)
(9/17) Purging linux-headers (4.19.36-r0)
(10/17) Purging make (4.2.1-r2)
(11/17) Purging isl (0.18-r0)
(12/17) Purging mpc1 (1.1.0-r1)
(13/17) Purging mpfr4 (4.0.2-r1)
(14/17) Purging python2 (2.7.16-r3)
(15/17) Purging gdbm (1.13-r1)
(16/17) Purging readline (8.0.1-r0)
(17/17) Purging sqlite-libs (3.30.1-r1)

runs before the time i need python

@JamesKyburz
Copy link

The latest node-gyp and python3 are now used in my docker image used to install native modules.

The reason I use this as a build step instead of installing python prior to npm install is for two reasons.

1.) The Docker image will be smaller
2.) Docker can cache all the dependencies required for native install even if you update package.json.

ᐅ docker run -ti --rm jameskyburz/node:10.18.0-alpine3.11-devtools sh
/ # node-gyp --version
v5.0.7
/ # python3 --version
Python 3.8.1
ᐅ docker run -ti --rm jameskyburz/node:12.14.0-alpine3.11-devtools sh
/ # node-gyp --version
v5.0.7
/ # python3 --version
Python 3.8.1

@zipzit
Copy link

zipzit commented Nov 7, 2020

I got stuck here using node:15.1.0-alpine3.12 Continual fail until I replaced python with python3.

@zacharytyhacz
Copy link

zacharytyhacz commented Nov 16, 2020

@zipzit same here, i'm using FROM node:15-alpine3.10 did you end up finding a solution? I am literally just trying to install python, it's super trivial.

Not working:

RUN apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python                           
RUN npm install --quiet node-gyp -g
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz: No such file or directory
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz: No such file or directory
ERROR: unsatisfiable constraints:
  g++ (missing):
    required by: world[g++]
  gcc (missing):
    required by: world[gcc]
  linux-headers (missing):
    required by: world[linux-headers]
  make (missing):
    required by: world[make]
  python (missing):
    required by: world[python]

And this earlier solution is not working:

RUN apk --no-cache add --virtual native-deps \
  g++ gcc libgcc libstdc++ linux-headers make python && \
  npm install --quiet node-gyp -g &&\
  npm install --quiet && \
  apk del native-deps
error /var/app/client/node_modules/node-sass: Command failed.
Exit code: 1
Command: node scripts/build.js
Arguments: 
Directory: /var/app/client/node_modules/node-sass
Output:
Building: /usr/local/bin/node /var/app/client/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
gyp info it worked if it ends with ok
gyp verb cli [
gyp verb cli   '/usr/local/bin/node',
gyp verb cli   '/var/app/client/node_modules/node-gyp/bin/node-gyp.js',
gyp verb cli   'rebuild',
gyp verb cli   '--verbose',
gyp verb cli   '--libsass_ext=',
gyp verb cli   '--libsass_cflags=',
gyp verb cli   '--libsass_ldflags=',
gyp verb cli   '--libsass_library='
gyp verb cli ]
gyp info using node-gyp@3.8.0
gyp info using node@15.2.0 | linux | x64
gyp verb command rebuild []
gyp verb command clean []
gyp verb clean removing "build" directory
gyp verb command configure []
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb `which` failed Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/var/app/client/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/app/client/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/app/client/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/app/client/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/app/client/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/app/client/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (node:fs:191:21)
gyp verb `which` failed  python2 Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/var/app/client/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/app/client/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/app/client/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/app/client/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/app/client/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/app/client/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (node:fs:191:21) {
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` failed Error: not found: python
gyp verb `which` failed     at getNotFoundError (/var/app/client/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/app/client/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/app/client/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/app/client/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/app/client/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/app/client/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (node:fs:191:21)
gyp verb `which` failed  python Error: not found: python
gyp verb `which` failed     at getNotFoundError (/var/app/client/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/app/client/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/app/client/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/app/client/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/app/client/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/app/client/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (node:fs:191:21) {
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp ERR! configure error 
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack     at PythonFinder.failNoPython (/var/app/client/node_modules/node-gyp/lib/configure.js:484:19)
gyp ERR! stack     at PythonFinder.<anonymous> (/var/app/client/node_modules/node-gyp/lib/configure.js:406:16)
gyp ERR! stack     at F (/var/app/client/node_modules/which/which.js:68:16)
gyp ERR! stack     at E (/var/app/client/node_modules/which/which.js:80:29)
gyp ERR! stack     at /var/app/client/node_modules/which/which.js:89:16
gyp ERR! stack     at /var/app/client/node_modules/isexe/index.js:42:5
gyp ERR! stack     at /var/app/client/node_modules/isexe/mode.js:8:5
gyp ERR! stack     at FSReqCallback.oncomplete (node:fs:191:21)
gyp ERR! System Linux 5.9.8-arch1-1
gyp ERR! command "/usr/local/bin/node" "/var/app/client/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /var/app/client/node_modules/node-sass
gyp ERR! node -v v15.2.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok 
Build failed with error code: 1

@zipzit
Copy link

zipzit commented Nov 16, 2020

I'm working in Node, React... my dockerfile:

#  ref: https://mherman.org/blog/dockerizing-a-react-app/
# pull official base image
FROM node:15.1.0-alpine3.12

# set working directory
WORKDIR /usr/src/app

# install app dependencies
COPY package.json ./
COPY package-lock.json ./

# Add Python per https://github.com/nodejs/docker-node/issues/384
# https://github.com/nodejs/docker-node/issues/282
# --no-cache: download package index on-the-fly, no need to cleanup afterwards
# --virtual: bundle packages, remove whole bundle at once, when done
RUN apk add --no-cache --virtual build-dependencies \
    python2 \
    python3 \
    make \
    g++ \
    && npm install \
    && apk del build-dependencies

# add `/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# add app
COPY . ./

# start app
CMD ["npm", "start"]

I only tried the python2, python3 thing in desperation, but it seems to work just fine.

And I'm not running from command line, instead I'm running from an integrated docker-compose.yml file. Note, this is still a work in progress. There may be errors below.. The dockerfile above is located within github.com/zipzit/privateRepoName. And I'm using the same container image for both frontend and backend servers.

version: "3.8"
services:
    mongo_db:
        image: mongo
        ports:
            - "27017:27017"
        volumes:
            - ./data:/data/db
        restart: on-failure:8
        environment:
          MONGO_INITDB_ROOT_USERNAME: xyz
          MONGO_INITDB_ROOT_PASSWORD: password
    mongo-express:
        image: mongo-express
        restart: always
        ports:
          - "8081:8081"
        links:
          - mongo_db
        depends_on:
          - mongo_db
        environment:
          ME_CONFIG_MONGODB_ADMINUSERNAME: xyz
          ME_CONFIG_MONGODB_ADMINPASSWORD: password
          ME_CONFIG_MONGODB_SERVER: mongo_db
    react_frontend:
        build: "https://${GIT_TOKEN}@github.com/zipzit/privateRepoName.git"
        ## working_dir: /usr/src/app
        ## working_dir: ""
        environment:
           - NODE_ENV=develop
           - REACT_APP_API_BASE_URL=http://192.168.1.15:8080/api
           - REACT_APP_IMAGE_URL=http://192.168.1.15:8080
           - REACT_APP_PUBLIC_URL=http://192.168.1.15:8080
        ports:
            - "3000:3000"
        container_name: "frontend_server"
        volumes:
            - ./frontend:/app'
            - '/app/node_modules'
    backend_server:
        build: "https://${GIT_TOKEN}@github.com/DifferentTeamMember/differentPrivateRepoName.git#master"
        user: "node"
        # working_dir: /usr/src/app
        environment:
            - NODE_ENV=develop
            - HOST=mongo_db
        ports:
          - "8080:8080"
        container_name: "backend_server"
        volumes:
          - ./backend:/usr/src/app
          - ./server_error_log:/usr/src/app/error.log
        links:
          - mongo_db
        depends_on:
          - mongo_db
volumes:
  frontend: {}
  backend: {}
  data: {}
  server_error_log: {}

@rwillians
Copy link
Author

Hey @zacharytyhacz, you gotta install python2 cuz the python package doesn't seem to be available anymore.

FROM node:15.1.0-alpine3.12

RUN apk --no-cache add --virtual native-deps \
    g++ gcc libgcc libstdc++ linux-headers make python2 && \
    npm install --quiet node-gyp -g

COPY package.json ./
COPY package-lock.json ./

RUN npm ci && \
    apk del native-deps

Btw I'm not sure if all those deps are required anymore

@millievn
Copy link

Hey @zacharytyhacz, you gotta install python2 cuz the python package doesn't seem to be available anymore.

FROM node:15.1.0-alpine3.12

RUN apk --no-cache add --virtual native-deps \
    g++ gcc libgcc libstdc++ linux-headers make python2 && \
    npm install --quiet node-gyp -g

COPY package.json ./
COPY package-lock.json ./

RUN npm ci && \
    apk del native-deps

Btw I'm not sure if all those deps are required anymore

works fine

@jmcbri
Copy link

jmcbri commented Jun 7, 2021

I got stuck here using node:15.1.0-alpine3.12 Continual fail until I replaced python with python3.
Where?

@rwillians
Copy link
Author

rwillians commented Jun 8, 2021

@jmcbri I'm guessing in your case you need take this snippet #384 (comment) and replace python2 with python3, resulting in:

FROM node:15.1.0-alpine3.12

RUN apk --no-cache add --virtual native-deps \
    g++ gcc libgcc libstdc++ linux-headers make python3 && \
    npm install --quiet node-gyp -g

COPY package.json ./
COPY package-lock.json ./

RUN npm ci && \
    apk del native-deps

@jmcbri
Copy link

jmcbri commented Jun 9, 2021

@jmcbri I'm guessing in your case you need take this snippet #384 (comment) and replace python2 with python3, resulting in:

FROM node:15.1.0-alpine3.12

RUN apk --no-cache add --virtual native-deps \
    g++ gcc libgcc libstdc++ linux-headers make python3 && \
    npm install --quiet node-gyp -g

COPY package.json ./
COPY package-lock.json ./

RUN npm ci && \
    apk del native-deps

Thanks. I'll give it a try. Have a great [time appropriate greeting]!

@malavshah9
Copy link

I fixed the issue by adding these lines to my docker file

RUN apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python
RUN npm install --quiet node-gyp -g

Thanks @Macmee . This helped me a lot.

@rwillians
Copy link
Author

Hey @malavshah9 👋
I’m glad that worked for you. If your using the alpine version of node image that means you care about your image size, so don’t forget the delete all dependencies and files that you don’t need during runtime. That’s why the recomended solution is longer than the one you used.

@malavshah9
Copy link

@rwillians Yes, I will do that also. Thanks for pointing out.

@piotr-cz
Copy link

There is a recipe for node-gyp alpine in this repo, that works just fine:

FROM node:alpine

RUN apk add --no-cache --virtual .gyp python make g++ \
    && npm install \
    && apk del .gyp

@rwillians
Copy link
Author

rwillians commented Aug 24, 2021

Nice @piotr-cz, we didn't have that back when the issue was created.
I believe those are the dependencies required for node-gyp itself. The node lib you need to install, which requires node-gyp, will probably require some additional dependencies so it's a good thing to keep an eye for that and install only what you need. The end result wouldn't be affect though if you install unecessary dependencies since we're deleting them right after npm install but but doing so would increase your build time in some situations.

I do recommend though to copy your package.json and/or package-lock.json file after you install the dependencies so that the dependencies cache layer don't get invalidated whenever your package files change. You'll get one extra layer for doing that (assuming you're not using multi-stage builds) but that's a tradeoff I'm often taking in favor of reduceing my build time.

@piotr-cz
Copy link

piotr-cz commented Aug 25, 2021

@rwillians My full Dockerfile is a mix of above recipe and Layer Caching from docker/getting-started repo:

FROM node:14-alpine
RUN apk add --no-cache --virtual .gyp python make g++

ENV NODE_ENV=production

WORKDIR /home/node/app

COPY package.json package-lock.json ./

RUN npm install && \
    apk del .gyp

COPY . .

EXPOSE 3000

CMD ["node", "src/index.js"]

Image created this way grew quite large (367MB) when compared to node:14-alpine (117MB) with app taking 72MB, however it's for another discussion. (after setting up mutli-stage build it's 149MB)

I guess best option is to avoid dependencies which require node-gyp when possible.

@srinivasan1211
Copy link

RUN apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python
RUN npm install --quiet node-gyp -g

when iam using this
python (no such package):
required by: world[python]
The command '/bin/sh -c apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python' returned a non-zero code: 1

got an error like this.

@rwillians
Copy link
Author

Hey @Sundar21, the package python seems to have been deprecated/dropped a while ago in favor of python2 and python3. Check out the discussion from this comment #384 (comment) and below. Lemme know if that helps

@rwillians
Copy link
Author

rwillians commented Apr 12, 2022

If you arrived at the issue, it probably means you’re new at using Docker and/or Node.js, like I was when I opened this issue 5 years ago. And that’s alright, I’ll try making it easier for you :)

We use alpine when we really care about that final image size (when you want it to be as small as possible), but that comes at a cost. If that’s not your case, please a try using a regular node image, such as node or node:17.8.0, and you should be good to go. If you really want that small image though, keep reading.

So what I mean by “cost” is that, in order to have a smaller image, you gotta remove unnecessary stuff from it — or better yet, never add the unnecessary stuff in the first place —. For example, alpine versions of node images, such as node:alpine and node:17.8.0-alpine, don’t come with python nor node-gyp installed, because they aren’t necessary in most cases. But some libs that you might use in your application, like the one I was using, requires to be built during their installation process using node-gyp, which requires python. Or, depending on your specific case, they might require something else.

Naturally, you’ll need to install those missing dependencies by yourself and once you don’t need them anymore, you gotta delete them. That’s the approach you’ll see on snippets throughout theses comments below. The most recent snippet is right below, just know that it might not fit your specific needs. It might be installing more stuff than you need or it might not be installing stuff that you actually need, in which case you’ll need to figure out the missing dependencies on your own by going through the logs. Of course you can ask for help here, me and a lot of the people participating in this discussion might be able to help you.

FROM node:17.8.0-alpine

WORKDIR /app

RUN apk --no-cache add --virtual virtual-deps \
    g++ gcc libgcc libstdc++ linux-headers make python2 && \
    npm install --quiet node-gyp -g

COPY package.json ./
COPY package-lock.json ./

RUN npm ci && \
    apk del virtual-deps

COPY src/ src/

EXPOSE 3000
CMD ["npm", "start"]

If you’re new to Docker, you should know that there’s another approach to address this issue using what’s called Multi-Stage Builds. This approach, applied to this issue, consists of using a base image (such as thee regular node image) that most likely contains everything needed to build your application. And then, once it’s built, you copy those files (application along with dependencies — node_modules) to a brand new image based on alpine, as you can see below:

FROM node:17.8.0 AS build-stage

WORKDIR /app

COPY package.json package.json
COPY package-lock.json package-lock.json

RUN npm ci


FROM node:17.8.0-alpine

WORKDIR /app

COPY --from=build-stage /app ./
COPY src/ src/

EXPOSE 3000
CMD ["npm", "start"]

I’m not in a good position to tell you which approach is better for you. For example, the second approach might take longer to build if you don't have cache but might be easier to work with while the first might be faster to build but it’s harder if you don’t know your way around finding the dependencies you need to install and also you gotta be more careful with how you cache the layers in order to get the optimal build time. So in my understanding, the best I can do is to tell you that you have these options and from here on, you can start exploring them on your own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests