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

Docs for using node-mapnik on AWS lambda #863

Open
springmeyer opened this issue Feb 28, 2018 · 14 comments
Open

Docs for using node-mapnik on AWS lambda #863

springmeyer opened this issue Feb 28, 2018 · 14 comments

Comments

@springmeyer
Copy link
Member

springmeyer commented Feb 28, 2018

As of the v3.7.0 release (per #839) the node-mapnik binaries for linux work on AWS lambda. We should have some brief docs on how to install on lambda. The one gocha is that you need to match the right node version otherwise you'll get and error on lambda at startup like:

Error: Module version mismatch. Expected 48, got 57.

This is fixable by ensuring that you either:

  1. Install locally on a linux machine with the same node version you are targeting on lambda, or;

  2. You "cross-install"

Cross-installing is passing specific flags to npm install that explicitly select linux as the operating system and an explicit node version you want to target. For more details see https://github.com/mapbox/node-pre-gyp#options.

For example, to install a binary for lambda using node v6 on OS X do:

npm install mapnik@3.7.0 --target=6.0.0 --target_arch=x64 --target_platform=linux

Note: this binary, while installable on OS X, is not going on run on OS X. The idea is that it will run on AWS lambda. If you tried to run it on OS X you'd see dlopen(/Users/dane/projects/tilelive-bridge/node_modules/mapnik/lib/binding/mapnik.node, 1): no suitable image found. since it is a linux binary.

@hwernstrom
Copy link

hwernstrom commented Jul 18, 2018

Edited: This seems to be a Cloud 9 issue and not a lambda issue

This works great for basic mapnik.
I'm using cloud 9 to test before pushing to lambda, the tests are showing that I can't load the default plugins.

My data is stored in postgres. Any ideas how to get the plugins to work.

Mapnik LOG> 2018-07-18 21:54:27: Problem loading plugin library: /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
Mapnik LOG> 2018-07-18 21:54:27: Problem loading plugin library: /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
Mapnik LOG> 2018-07-18 21:54:27: Problem loading plugin library: /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/sqlite.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
PASS tests/mapper.test.js4:27: Problem loading plugin library: /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/csv.in

@springmeyer
Copy link
Member Author

@hwernstrom what is the output of:

ldd /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input

Also what is the error if you try to open one of the plugins with the python ctypes module like described at https://github.com/mapnik/node-mapnik/wiki/Troubleshooting#the-specified-module-cannot-be-found?

@hwernstrom
Copy link

This appears to be an issue with the Cloud9 env, this works fine in lambda. I'm using Cloud9 as my dev because I thought it would closely match Lambda.

Here are the results from Clould9.

/home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input)
linux-vdso.so.1 => (0x00007ffefdd1e000)
libmapnik.so => /home/ec2-user/environment/serverless/packages/aip-maps/node_modules/mapnik/lib/binding/lib/mapnik/input/../../libmapnik.so (0x00007f9e78d22000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f9e78aeb000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f9e787e7000)
libm.so.6 => /lib64/libm.so.6 (0x00007f9e784e5000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f9e782cf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f9e77f0b000)
libz.so.1 => /lib64/libz.so.1 (0x00007f9e77cf5000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f9e77af1000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f9e778d5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9e7a37f000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f9e776d3000)

@calvinmetcalf
Copy link
Contributor

Just fyi, on google cloud functions, I was able to use this with no extra steps. So great job folks.

@ScottSmudger
Copy link

ScottSmudger commented Jun 10, 2020

Is this still the recommended way to do this or is there more to be done?

Initially I had issues with libmapnik.so.4.0 not existing, so as part of my lambda deploy process I cp libmapnik.so to libmapnik.so.4.0 from within the node_modules/mapnik/lib/binding/lib directory. This dir is then set as an environment variable in lambda as LD_LIBRARY_PATH.

However I'm getting the following errors in the lambda logs:

Mapnik LOG> 2020-06-10 21:54:40: Problem loading plugin library: /var/task/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
Mapnik LOG> 2020-06-10 21:54:40: Problem loading plugin library: /var/task/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)

I'm new to the lambda/mapnik and OSM game so any advice to getting mapnik running in aws lambda would be great.

Thanks!

@timothypage
Copy link

@ScottSmudger I had to add libcrypt.so.1 to the zip to get the postgres stuff to work for me... grabbed it out of /lib64/ from the "Amazon Linux 2" ami

@knutole
Copy link

knutole commented Feb 20, 2021

I'm having the same issue. Seems it's only related to postgis.input and pgraster.input, as the other modules load fine. What's special about those two?

Error message in Lambda:

Mapnik LOG> 2021-02-20 01:55:32: Problem loading plugin library: /opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
Mapnik LOG> 2021-02-20 01:55:32: Problem loading plugin library: /opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/pgraster.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)
Mapnik LOG> 2021-02-20 01:55:32: Problem loading plugin library: /opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)

Pseudocode, handler.js Lambda function

const path = require('path');
const mapnik = require('mapnik');

module.exports.raster = function (event, context) {

    mapnik.register_default_fonts();
    mapnik.register_default_input_plugins();
    mapnik.register_datasource(path.join(mapnik.settings.paths.input_plugins,'postgis.input'));

};

Versions

  • I'm running Lambda NodeJS 12.x.
  • I'm using node-mapnik binary v4.5.6. I have also tested v4.4.0 and v4.5.0.
  • I'm building npm package using lambci/lambda:build-nodejs12.x, like so:
docker run -it -v $PWD:/opt/nodejs -w /opt/nodejs lambci/lambda:build-nodejs12.x npm install --save github:mapnik/node-mapnik#v4.5.6

This add modules to the correct path for Lambda, as far as I understand: /opt/nodejs/node_modules. The build- and run environment should also be identical (lambci/lambda:build-nodejs12.x == lambci/lambda:nodejs12.x)

LDD's

bash-4.2# ldd /opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input
	linux-vdso.so.1 (0x00007ffc811c1000)
	libmapnik.so => /opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/./../../libmapnik.so (0x00007ffb3f221000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007ffb3efea000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ffb3ec68000)
	libm.so.6 => /lib64/libm.so.6 (0x00007ffb3e928000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffb3e712000)
	libc.so.6 => /lib64/libc.so.6 (0x00007ffb3e367000)
	libz.so.1 => /lib64/libz.so.1 (0x00007ffb3e152000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007ffb3df4e000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffb3dd30000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ffb40c07000)
bash-4.2# ldd /opt/nodejs/node_modules/mapnik/lib/binding/lib/libmapnik.so
	linux-vdso.so.1 (0x00007ffcb790f000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f29e1547000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f29e1343000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f29e0fc1000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f29e0c81000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f29e0a6b000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f29e084d000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f29e04a2000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f29e2ebe000)

Environment

Some env variables inside Lambda fn:

  LD_LIBRARY_PATH: '/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib',
  NODE_PATH: '/opt/nodejs/node12/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task',
  ICU_DATA: '/opt/nodejs/node_modules/mapnik/lib/binding/share/icu',
  GDAL_DATA: '/opt/nodejs/node_modules/mapnik/lib/binding/share/gdal',
  PROJ_LIB: '/opt/nodejs/node_modules/mapnik/lib/binding/share/proj',

mapnik.settings

mapnik.settings: {
  paths: {
    fonts: '/opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/fonts',
    input_plugins: '/opt/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input',
    mapnik_index: '/opt/nodejs/node_modules/mapnik/lib/binding/bin/mapnik-index',
    shape_index: '/opt/nodejs/node_modules/mapnik/lib/binding/bin/shapeindex'
  },
  env: {
    ICU_DATA: '/opt/nodejs/node_modules/mapnik/lib/binding/share/icu',
    GDAL_DATA: '/opt/nodejs/node_modules/mapnik/lib/binding/share/gdal',
    PROJ_LIB: '/opt/nodejs/node_modules/mapnik/lib/binding/share/proj'
  }
}

@springmeyer
Copy link
Member Author

@knutole try using ctypes.CDLL to open the postgis.input like https://github.com/mapnik/node-mapnik/wiki/Troubleshooting#the-specified-module-cannot-be-found. That might expose a more helpful error which will likely point to missing GLIBCXX symbols. If that is what is missing then the libstdc++ version would need upgraded and if that is not possible then it means the version of node-mapnik is using too modern a c++ version to run in the lambda env.

@knutole
Copy link

knutole commented Feb 20, 2021

@springmeyer Thanks. I'm getting different results?

Using python:3 Docker image: 

knutole@knutole ~/m/m/nodejs> docker run -it -v $PWD:/opt/nodejs -w /opt/nodejs python:3 python3
Python 3.8.1 (default, Jan  3 2020, 22:44:00)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input')
<CDLL 'node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input', handle 55ea4c5e3830 at 0x7f631b01cc70>

Using OSX python 2:

Python 2.7.16 (default, Dec 21 2020, 23:00:36)
[GCC Apple LLVM 12.0.0 (clang-1200.0.30.4) [+internal-os, ptrauth-isa=sign+stri on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('mapnik/lib/binding/lib/mapnik/input/postgis.input')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 366, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(mapnik/lib/binding/lib/mapnik/input/postgis.input, 6): no suitable image found.  Did find:
	mapnik/lib/binding/lib/mapnik/input/postgis.input: unknown file type, first eight bytes: 0x7F 0x45 0x4C 0x46 0x02 0x01 0x01 0x00
	/Users/knutole/mile-lambda/mapnik-layer/nodejs/node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input: unknown file type, first eight bytes: 0x7F 0x45 0x4C 0x46 0x02 0x01 0x01 0x00

@knutole
Copy link

knutole commented Feb 20, 2021

@springmeyer Do you have any suggestions of node-mapnik binary versions that are liable to work better, against either Node12.x or Node10.x (or even any other Node version)?

I'm not sure if the node-mapnik binaries are meant to run on Amazon Linux 2? https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html

@springmeyer
Copy link
Member Author

@knutole a couple thoughts:

  1. Your error with python 2 looks related to an incorrect path.
  2. The fact that python3 is not throwing an error is likely because you are using an image that does not have the same environment as lambda does. So I think to run a proper test to try to expose the actual error that is likely happening you'll need to use a docker image of amz linux 2
  3. In terms of what versions of node-mapnik work on lambda, all I know is that mapnik@3.7.0 did with node v6. But I would not be surprised at all if the support regressed since

@knutole
Copy link

knutole commented Feb 20, 2021

@springmeyer Thanks again.

I've added Python3 to the offical lambci/lambda:build-nodejs12.x image, which is more or less identical to the Lambda image running on AWS.

FROM lambci/lambda:build-nodejs12.x
RUN yum install -y python3

Running it, all seems well?

knutole@knutole ~/m/m/nodejs> docker run -it -v $PWD:/opt/nodejs -w /opt/nodejs lambda-nodejs12-python3:latest python3
Python 3.7.9 (default, Feb 18 2021, 03:10:35)
[GCC 7.3.1 20180712 (Red Hat 7.3.1-12)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input')
<CDLL 'node_modules/mapnik/lib/binding/lib/mapnik/input/postgis.input', handle ca6810 at 0x7ff583f894d0>

I wonder why it's only postgis.input and pgraster.input that fail, though...? Any way to debug this directly from a nodejs script (on Lamdba)? I will try to run the code in a local lambci/lambda:nodejs12.x image, but it should be the same result.

PS: nodejs6 is already EOL on Lambda. :/

@springmeyer I've built and run the code on a local lambci/lambda:nodejs12.x, after adding binary using lambci recommended method,

docker run --rm -v "$PWD":/var/task lambci/lambda:build-nodejs12.x npm install github:mapnik/node-mapnik#v4.5.6

but ctypes.CDLL() still seems to load it fine, so I think we can rule this one out.

Any way to get more debugging info? CI build logs? Anything??

Perhaps it's got something to do with some dependencies only postgis/pgraster uses? Is everything included in node-mapnik binary, or are there some PG related dependencies that need to be added?

@knutole
Copy link

knutole commented Feb 20, 2021

Brilliant solution that works, here: #937 (comment)! 💯 Thanks again for your time, @springmeyer.

For future reference: I built node-mapnik#v4.5.6 with a node:12 Docker image, then used the custom lambci nodejs12 image arn:aws:lambda:<region>:553035198032:layer:nodejs12:39. Works perfectly.

@molandim
Copy link

@ScottSmudger I had to add libcrypt.so.1 to the zip to get the postgres stuff to work for me... grabbed it out of /lib64/ from the "Amazon Linux 2" ami

Super!!!

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

No branches or pull requests

7 participants