Created a Docker Image to Call FBX SDK Python from Node.js

This article is a translated version of my original post on Qiita. Original (Japanese): https://qiita.com/segur/items/5d068661b12a1e7717d2

Created a Docker Image to Call FBX SDK Python from Node.js

Due to certain requirements, I needed to call FBX SDK Python from Node.js, so I created a Docker image.

The Docker image I created is published at the following link: https://hub.docker.com/r/seguropus/fbx-sdk-python-nodejs

Sample Code

The sample code is available here: https://github.com/segurvita/docker-fbx-sdk-python-nodejs

How to Use the Sample Code

# Build the Docker image
docker-compose build

# Start the Docker container
docker-compose up

If the following display appears, it indicates success:

fbx-sdk-python-nodejs    | # FBX SDK can read the following formats.
fbx-sdk-python-nodejs    | 00 FBX (*.fbx)
fbx-sdk-python-nodejs    | 01 AutoCAD DXF (*.dxf)
fbx-sdk-python-nodejs    | 02 Alias OBJ (*.obj)
fbx-sdk-python-nodejs    | 03 3D Studio 3DS (*.3ds)
fbx-sdk-python-nodejs    | 04 Collada DAE (*.dae)
fbx-sdk-python-nodejs    | 05 Alembic ABC (*.abc)
fbx-sdk-python-nodejs    | 06 Biovision BVH (*.bvh)
fbx-sdk-python-nodejs    | 07 Motion Analysis HTR (*.htr)      
fbx-sdk-python-nodejs    | 08 Motion Analysis TRC (*.trc)      
fbx-sdk-python-nodejs    | 09 Acclaim ASF (*.asf)
fbx-sdk-python-nodejs    | 10 Acclaim AMC (*.amc)
fbx-sdk-python-nodejs    | 11 Vicon C3D (*.c3d)
fbx-sdk-python-nodejs    | 12 Adaptive Optics AOA (*.aoa)      
fbx-sdk-python-nodejs    | 13 Superfluo MCD (*.mcd)
fbx-sdk-python-nodejs    | 14 (*.zip)
fbx-sdk-python-nodejs exited with code 0

The listed formats are those that FBX SDK can read.

This indicates that you're successfully accessing FBX SDK Python.

What Happens Behind the Scenes?

First, when you run docker-compose up, the Docker container starts.

Once up, the Docker container executes the Node.js code in index.js.

The index.js script calls the Python code main.py.

The main.py script retrieves and displays the supported formats list from FBX SDK Python.

Dockerfile

I based the Dockerfile on a Docker image that already integrates Python and Node.js.

# Alpine with Python 2.7 and Node.js 12
FROM nikolaik/python-nodejs:python2.7-nodejs12-alpine

# Update libraries using apk
RUN apk update && \
    apk add \
    curl \
    libxml2 \
    libstdc++

# Download FBX SDK
RUN curl -L \
    https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/20195/fbx20195_fbxpythonsdk_linux.tar.gz \
    -o /tmp/fbx20195_fbxpythonsdk_linux.tar.gz

# Create installation directory
RUN mkdir -p /python-fbx/install

# Extract FBX SDK
RUN tar -zxvf \
    /tmp/fbx20195_fbxpythonsdk_linux.tar.gz \
    -C /python-fbx && \
    printf "yes\nn" | \
    /python-fbx/fbx20195_fbxpythonsdk_linux \
    /python-fbx/install

# Install FBX SDK
RUN cp /python-fbx/install/lib/Python27_ucs4_x64/* \
    /usr/local/lib/python2.7/site-packages/

# Install python-shell
RUN npm install -g python-shell

# Remove temporary files
RUN rm -r /python-fbx
RUN rm /tmp/fbx20195_fbxpythonsdk_linux.tar.gz

# Set NODE_PATH environment variable
ENV NODE_PATH /usr/local/lib/node_modules

python-shell is a library used to call Python from Node.js.

It's installed globally, so the NODE_PATH environment variable is set to make it accessible to index.js.

docker-compose.yml

The docker-compose.yml file is structured as follows:

version: '3'
services:
  fbx-sdk-python-nodejs:
    image: 'seguropus/fbx-sdk-python-nodejs'
    container_name: 'fbx-sdk-python-nodejs'
    build:
      context: ./
      dockerfile: ./Dockerfile
    volumes:
      - .:/src
    working_dir: /src
    command: node index.js

The command index.js is executed upon starting the Docker container.

index.js

The index.js script looks like this:

const pythonShell = require('python-shell');

// Options for python-shell
const pyOption = {
    mode: 'text',
    pythonPath: '/usr/local/bin/python',
    pythonOptions: ['-u'],
    scriptPath: '/src',
}

// Execute main.py
const pyShell = new pythonShell.PythonShell('main.py', pyOption);

// Show Python's standard output
pyShell.on('message', (message) => {
    console.log(message);
});

// Handle exit
pyShell.end(function (err, code, signal) {
    if (err) {
        console.error(err);
    }
    console.log('The exit code was: ' + code);
});

This script uses python-shell to invoke main.py.

main.py

Here's the main.py script:

from fbx import *


def list_reader_format(manager):
    print('# FBX SDK can read the following formats.')
    for formatIndex in range(manager.GetIOPluginRegistry().GetReaderFormatCount()):
        description = manager.GetIOPluginRegistry().GetReaderFormatDescription(formatIndex)
        print(formatIndex, description)


def main():
    # Create
    manager = FbxManager.Create()
    scene = FbxScene.Create(manager, "fbxScene")

    # List
    list_reader_format(manager)

    # Destroy
    scene.Destroy()
    manager.Destroy()


if __name__ == '__main__':
    main()

This script imports FBX SDK Python with from fbx import * and lists all file formats that FBX SDK Python can read using the function list_reader_format().

Successfully, I was able to create a Docker image that allows Node.js to call FBX SDK Python!

Publishing on Docker Hub

Since I went through the effort, I published it on Docker Hub.

# Log in
docker login

# Push the Docker image
docker push seguropus/fbx-sdk-python-nodejs

It is published here: https://hub.docker.com/r/seguropus/fbx-sdk-python-nodejs

In Conclusion

In creating this article, I referred to the following pages. Thank you for your valuable resources: