Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to install Python on nodejs Docker image

I have a nodejs application that works on my machine since I have python installed and it's in the global env PATH (also in process.env.PATH) so I can run:

const spawn = require("child_process").spawn;
 console.log('PATH:::::');
 console.log(process.env.PATH);
 const pythonProcess = spawn('python', ["./detect_shapes.py", './example2.png']);
 pythonProcess.stdout.on('data', (data) => {
 console.log('DATA::::');
 console.log(data);
 res.render('index', {data});
});

The script above basically runs a separate python script inside my nodejs application and returns a response to it. I can run the basic commands that can be found on any machine like this: const pythonProcess = spawn('ls');. This line of code will run the ls command and return the files as it is expected to do.

I also have a Dockerfile like this:

FROM node:9-slim
WORKDIR /app 
COPY . /app 
RUN npm install 
EXPOSE 3000 
CMD ["node", "index.js"]

I created nodejs applications with this exact Dockerfile config and it worked, since I am using child_process.spawn functions it maybe doesn't know about python or it's path so I am getting this error:

Error: spawn python ENOENT
 at Process.ChildProcess._handle.onexit (internal/child_process.js:201:19)
 at onErrorNT (internal/child_process.js:379:16)
 at process._tickCallback (internal/process/next_tick.js:178:19)
Emitted 'error' event at:
 at Process.ChildProcess._handle.onexit (internal/child_process.js:207:12)
 at onErrorNT (internal/child_process.js:379:16)
 at process._tickCallback (internal/process/next_tick.js:178:19)

I tried adding a RUN apt-get install python -y in my Dockerfile for it to install python in my docker image and I can use python, but it doesn't work. Do I have to add another FROM <image> that can install python (I am thinking that node:9-slim doesn't know how to install python since it's not used for that) in the Dockerfile so docker knows how to download python so I can use it.

Also when I print process.env.PATH on my docker container I get this: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin. How can I know that I have python working on my image and/or how can I add it to my paths if that is the problem?

I am new to Docker. I learned it yesterday, so if I didn't make things clear or you need more information please PM me or leave a comment.

like image 603
Amir Šaran Avatar asked Jul 06 '19 11:07

Amir Šaran


People also ask

Can I install Python in a docker container?

How to install Python in a Docker Container? It will download the ubuntu images from the docker hub and run the container in the background. You can check it using the docker ps command. Now let's go inside the container using the docker exec command and install python in it.

How do I install Python packages in docker?

To install packages in a docker container, the packages should be defined in the Dockerfile. If you want to install packages in the Container, use the RUN statement followed by exact download command . You can update the Dockerfile with latest list of packages at anytime and build again to create new image out of it.


1 Answers

In fact, this is not a docker question, just a debian question. You need always do apt-get update before install package. So, for you scenario, it should be:

RUN apt-get update || : && apt-get install python -y

As per your comments:

W: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/InRelease Unable to find expected entry 'main/binary-amd64/Packages' in Release file (Wrong sources.list entry or malformed file) E: Some index files failed to download. They have been ignored, or old ones used instead. The command '/bin/sh -c apt-get update && apt-get install python -y' returned a non-zero code: 100

So, you can add || : after apt-get to ignore the error, as at that time python meta data already finished downloading with other previous url hit, so you can bypass the error.

Update:

A whole workable solution in case you need to compare:

a.py:

print("success")

index.js:

const spawn = require("child_process").spawn;
console.log('PATH:::::');

console.log(process.env.PATH);
const pythonProcess = spawn('python', ['/app/a.py']);
pythonProcess.stdout.on('data', (data) => {
    console.log('DATA::::');
    console.log(data.toString());
});

pythonProcess.stderr.on('data', (data) => {
    console.log("wow");
    console.log(data.toString());
});

Dockerfile:

FROM node:9-slim

RUN apt-get update || : && apt-get install python -y

WORKDIR /app
COPY . /app
CMD ["node", "index.js"]

Try command:

orange@orange:~/gg$ docker build -t abc:1 .
Sending build context to Docker daemon  4.096kB
...
Successfully built 756b13952760
Successfully tagged abc:1

orange@orange:~/gg$ docker run abc:1
PATH:::::
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DATA::::
success
like image 136
atline Avatar answered Oct 16 '22 11:10

atline