Search code examples
pythondockerdockerfilecontainersoctave

Configure a docker container as environment variable in another container


I have a docker container that executes octave-cli, what I want is to have that executable as an environmental variable in another container so that I could run it using a python script.

I am using oct2py library in my python script which requires an environmental variable with octave executable. There is no PPA with the latest version of octave that is required hence I found an octave docker image(mtmiller/octave) that works well with my .m files. Now I want it to be available in my python container so that the script works.

Example octave script

function hello()
    printf("hello,world!")
endfunction

Python script

from oct2py import octave
octave.add('path/to/octavefile')
octave.hello()

Output

hello,world!

Requirement to run above python script

You must have GNU Octave installed and in your PATH environment variable. Alternatively, you can set an OCTAVE_EXECUTABLE or OCTAVE environment variable that points to octave-cli executable itself.

Now, I have mtmiller/octave that executes octave. How to set it in the PATH of the python container?


Solution

  • I suspect octave offers a web api package thing .... but i have no idea about it but you could run a lightweight flask api server on your octave server

    octave docker image

    octave-server.py

    import flask
    import subprocess
    from oct2py import octave
    octave.add('path/to/octavefile')
    
    app = flask.Flask(__name__)
    @app.route("hello.m")
    def hello_fn_call():
        users_name = flask.request.args.get("name")
        return json.dumps(octave.hello(users_name))
    
    if __name__ == "__main__":
        # you should really serve this with nginx + gunicorn or something
        app.run(debug=True)
    

    python docker image

    octave_rest.py

    import requests
    def say_hello(username):
        return requests.get("http://other-image:5000/hello.m",{"name":username}).json()
    if __name__ == "__main__":
        print(say_hello("BOB"))
        # something like "Hello, Bob"
    

    if you really want to print strings in your octave program you will need to capture the standard out, this decorator should help (of coarse you can do it all manually also)

    from contextlib import redirect_stdout # py3.4+ only
    import io
    
    ...
    
    @app.route("hello.m")
    def hello_fn_call():
        users_name = flask.request.args.get("name")    
        f = io.StringIO()
        with redirect_stdout(f):
            hello(users_name) # capture stdout
        return json.dumps(f.getvalue())