From 23f4a6336408b1cf938bea4722bcfc905f4a1471 Mon Sep 17 00:00:00 2001 From: ozan Date: Sat, 31 Dec 2022 21:39:28 +0300 Subject: [PATCH] docker example --- .gitignore | 1 + docker-example/.dockerignore | 2 + docker-example/Dockerfile | 26 ++++++++++++ docker-example/README.md | 69 ++++++++++++++++++++++++++++++++ docker-example/package-lock.json | 59 +++++++++++++++++++++++++++ docker-example/package.json | 15 +++++++ docker-example/requirements.txt | 3 ++ docker-example/src/example.py | 10 +++++ docker-example/src/index.js | 27 +++++++++++++ 9 files changed, 212 insertions(+) create mode 100644 docker-example/.dockerignore create mode 100644 docker-example/Dockerfile create mode 100644 docker-example/README.md create mode 100644 docker-example/package-lock.json create mode 100644 docker-example/package.json create mode 100644 docker-example/requirements.txt create mode 100644 docker-example/src/example.py create mode 100644 docker-example/src/index.js diff --git a/.gitignore b/.gitignore index 7bd3438..2226293 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /node_modules +docker-example/node_modules /Python-3.7.3 /build /.vscode diff --git a/docker-example/.dockerignore b/docker-example/.dockerignore new file mode 100644 index 0000000..1750f25 --- /dev/null +++ b/docker-example/.dockerignore @@ -0,0 +1,2 @@ +__pycache__ +node_modules \ No newline at end of file diff --git a/docker-example/Dockerfile b/docker-example/Dockerfile new file mode 100644 index 0000000..9ef65d5 --- /dev/null +++ b/docker-example/Dockerfile @@ -0,0 +1,26 @@ +FROM nikolaik/python-nodejs:python3.8-nodejs18-slim + +WORKDIR /usr/app +#prepare packages to install pynode +RUN apt update -qq && apt install make gcc g++ -y + +#prepare npm, shared folder is copied +#prepare pynode +COPY package.json . + +RUN npm install @fridgerator/pynode +RUN npm install + +#prepare python requirements +COPY requirements.txt . +RUN pip3 install -r requirements.txt + +#prepare project files +COPY ./src . + +CMD ["node", "index.js"] + + + + + diff --git a/docker-example/README.md b/docker-example/README.md new file mode 100644 index 0000000..2f95679 --- /dev/null +++ b/docker-example/README.md @@ -0,0 +1,69 @@ +#Dockerizing + +Dockerizing a pynode application is easy. + +This example uses one of nikolaik/python-nodejs image. +nikolaik's image repository has all combinations of python and nodejs versions so thats a good start. +You can use a python base image and compile a node +or +use a base nodejs image and compile python + +using python3.8 and node 18 +``` +FROM nikolaik/python-nodejs:python3.8-nodejs18-slim + +WORKDIR /usr/app +``` + +We need to install additional platform packages in order to build pynode app thus it uses node-addons we should able to compile the module +So we are installing required packages as following + +``` +RUN apt update -qq && apt install make gcc g++ -y +``` + +It is not required but making sure that pynode is compiling we explicitly run install command for pynode npm package +``` +COPY package.json . +RUN npm install @fridgerator/pynode +RUN npm install +``` + +It is bespractice to work with virtual environment for python applications. +Once your development has finished, pip freeze > requirements.txt will produces dependency file. +Then copy this file and install the requirements in docker image + +``` +COPY requirements.txt . +RUN pip3 install -r requirements.txt +``` + +Now image is ready to execute a pynode application. +You can checkout Dockerfile for details and customize according to your needs. + +## Tips + +There are multiple python versions depending on the platform and python version, the place of the shared python library could vary and can results problems in the runtime. To prevent this, pynode has dlOpen option to meet required libpython to the application. + +If you cant sure where is the python lib, you can use find_libpython python package to locate. +It automatically finds the proper library location according to version and platform. + +It can be used as follows to introduce libpython to the pynode application. You can checkout index.js for detailed example. + +``` +const {spawnSync} = require('child_process'); +libpython_proc = spawnSync('find_libpython'); +if(libpython_proc.status != 0){ + throw Error(libpython_proc.error); +} + +path = libpython_proc.stdout.toString().trim(); + +pynode.dlOpen(path); +``` + + + + + + diff --git a/docker-example/package-lock.json b/docker-example/package-lock.json new file mode 100644 index 0000000..8cc7c31 --- /dev/null +++ b/docker-example/package-lock.json @@ -0,0 +1,59 @@ +{ + "name": "docker-example", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "docker-example", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@fridgerator/pynode": "^0.5.2", + "findlibpython": "^1.0.0" + } + }, + "node_modules/@fridgerator/pynode": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@fridgerator/pynode/-/pynode-0.5.2.tgz", + "integrity": "sha512-4YjcmBRUDHxcbB+DlKHnV1NGnO8PWyQzC1Y5SoK5RGnzf8SMn+PyT33b5ptuDO2CcqiBK/POabEX7d8P0p8Efw==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^1.7.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/findlibpython": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/findlibpython/-/findlibpython-1.0.0.tgz", + "integrity": "sha512-NQR+R1tMGk/QDLyxtMAUw8Ev3JeM5eLfsFpF7vG3apUd7I39KUpGBDbxckBVYHid/HHczVTZFRY4h9RCpwo/dw==" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + } + }, + "dependencies": { + "@fridgerator/pynode": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@fridgerator/pynode/-/pynode-0.5.2.tgz", + "integrity": "sha512-4YjcmBRUDHxcbB+DlKHnV1NGnO8PWyQzC1Y5SoK5RGnzf8SMn+PyT33b5ptuDO2CcqiBK/POabEX7d8P0p8Efw==", + "requires": { + "node-addon-api": "^1.7.1" + } + }, + "findlibpython": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/findlibpython/-/findlibpython-1.0.0.tgz", + "integrity": "sha512-NQR+R1tMGk/QDLyxtMAUw8Ev3JeM5eLfsFpF7vG3apUd7I39KUpGBDbxckBVYHid/HHczVTZFRY4h9RCpwo/dw==" + }, + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + } + } +} diff --git a/docker-example/package.json b/docker-example/package.json new file mode 100644 index 0000000..e714291 --- /dev/null +++ b/docker-example/package.json @@ -0,0 +1,15 @@ +{ + "name": "docker-example", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@fridgerator/pynode": "^0.5.2", + "findlibpython": "^1.0.0" + } +} diff --git a/docker-example/requirements.txt b/docker-example/requirements.txt new file mode 100644 index 0000000..82d218b --- /dev/null +++ b/docker-example/requirements.txt @@ -0,0 +1,3 @@ +find-libpython==0.3.0 +numpy==1.24.1 +scipy==1.9.3 diff --git a/docker-example/src/example.py b/docker-example/src/example.py new file mode 100644 index 0000000..3a0a8fc --- /dev/null +++ b/docker-example/src/example.py @@ -0,0 +1,10 @@ +import scipy +import os +def test(): + #print python version + print("python version:",os.sys.version) + #print current working directory + print("cwd:",os.getcwd()) + #print environment variables + print(scipy.rand()) + return True \ No newline at end of file diff --git a/docker-example/src/index.js b/docker-example/src/index.js new file mode 100644 index 0000000..695f7b9 --- /dev/null +++ b/docker-example/src/index.js @@ -0,0 +1,27 @@ +//call subprocess and wait answer sync +const pynode = require('@fridgerator/pynode'); +const {spawnSync} = require('child_process'); + + +libpython_proc = spawnSync('find_libpython'); +if(libpython_proc.status != 0){ + // console.log(libpython_proc) + throw Error(libpython_proc.error); +} + +path = libpython_proc.stdout.toString().trim(); + +pynode.dlOpen(path); + +pynode.startInterpreter(); + +//tell pynode where python script are +pynode.appendSysPath(__dirname); + +pynode.openFile('example'); + +// call the python function and get a return value +pynode.call('test', (err, result) => { + if (err) return console.log('error : ', err); + console.log('result : ', result); +});