Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Dockerizing Wolfram Mathematica

In case you have docker in your system you can just pull the base image from here and jump to section (Install Wolfram on the base image). To keep things self contained, in the following I build the base image from scratch and install docker on Linux.

Set up Docker in your system

  1. Update the apt package index:

    sudo apt-get update
  2. Install packages to allow apt to use a repository over HTTPS:

    sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        software-properties-common
  3. Add Docker’s official GPG key:

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Add The Docker Repository

For latest Ubuntu LTS 18.04 there was no stable version. Create a new file for the Docker repository at /etc/apt/sources.list.d/docker.list. In that file, place one of the following lines choosing either stable, nightly or edge builds:

STABLE (NOT YET AVAILABLE!), please check availability before using:

deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
EDGE:
deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic edge
NIGHTLY:
deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic nightly

Install Docker CE

You can simply install the Docker CE package.

sudo apt install docker-ce

Done. Check for docker version:

docker --version
Docker version 18.03.0-ce, build 0520e24

Create a base image for Wolfram

To create the docker group and add your user:

  1. Create the docker group.

    sudo groupadd docker
  2. Add your user to the docker group.

    sudo usermod -a -G docker $USER
  3. Log out and log back in so that your group membership is re-evaluated.

    If testing on a virtual machine, it may be necessary to restart the virtual machine for changes to take effect. Now we do a docker pull of this image here. It comes with ssh installed and latest Ubuntu 18.04. Check the run example and log into docker console.

  4. Once inside the docker console, now we install some necessary packages to make the wolfram base image. Also to directly run a command over ssh one can use sshpass.

    apt-get -y install \
    	build-essential \
    	mosquitto \
    	mosquitto-clients \
    	avahi-daemon \ 
    	avahi-discover \
    	avahi-utils \
    	libnss-mdns \
    	mdns-scan \
    	sshpass
  5. Install Node.js and pip3 for Python 3.6.5 inf you want the ExternalEvaluate to work in Wolfram Mathematica 11.3.0.

    curl -sL https://deb.nodesource.com/setup_10.x | bash -

    You can successfully add Node.js PPA to Ubuntu system. Now execute the below command install Node on and Ubuntu using apt-get.

    apt-get install nodejs
    apt-get install python3-pip
  6. Activate avahi-daemon systemctl enable avahi-daemon.

Commit the base image

Now exit from bash and commit the image and name it wolfram-base

docker commit f750854c1c60 wolfram-base

Install Wolfram on the base image

Run it with a host directory /host/directory/installer mounted where the Mathematica installation file (Mathematica_11.3.0_LINUX.sh) is. The installer now will be available in the mounted directory /mma inside the docker container:

docker run -d -P -v "/host/directory/installer:/mma" wolfram-base

Now we should check the container ID (6daa3df35b93) and go to Ubuntu bash and install Mathematica inside the container.

$ docker ps
$ docker exec -it 6daa3df35b93 bash
$ cd /mma
$ bash ./Mathematica_11.3.0_LINUX.sh

Register Node.js and Python tag and commit docker image

If the Node.js and Python binding needs to be installed by default we can register them at this stage. Our base image was made to support this feature. Type wolfram in the terminal and evaluate the following and quit wolfram.

FindExternalEvaluators["NodeJS"]
FindExternalEvaluators["Python"]

We should now exit from the bash and do a docker commit to save the state of the image.

$ docker commit 6daa3df35b93 wolfram-docker-11.3.0

At this point we will have these images.

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
wolfram-docker-11.3.0    latest              6daa3df35b93        2 minutes ago       10.9GB
wolfram-base             latest              dcd0a3d55be0        About an hour ago   685MB
rastasheep/ubuntu-sshd   18.04               08f01ce8fd9f        15 hours ago        234MB

Now just login( assuming userid) to docker and tag your image and push it to the docker hub.

$ docker tag wolfram-docker-11.3.0:latest userid/wolfram-docker-11.3.0
$ docker push userid/wolfram-docker-11.3.0

Push your image to docker hub

Once the image is ready we should now tag it and push to docker hub. Docker may ask you to login if you have not already. The image is 11 GB and it can take time to upload to docker hub.

$ docker tag wolfram-docker-11.3.0:latest userid/wolfram-docker-11.3.0
$ docker push userid/wolfram-docker-11.3.0:latest

Now you can pull this docker image and run on may machine that has docker.

Test it!

We can run now our docker container in a detached mode. Use docker ps to note the container id. Note that we are mounting the host /home directory as /mma inside our docker. We will host networking here.

$ docker run -dti -P --network host  -v "/home:/mma" wolfram-docker-11.3.0:latest bash

Now time to login to the console of the docker container.

$ docker exec -ti 602c2dbd8dce bash

Write some Wolfram language code.

  1. To test the Python external connection a bit of code from doc section.

    script=FileNameJoin[{$TemporaryDirectory,"functions.py"}];
    Export[script,"def stringreverse(s):
        return s[::-1]
    def stringallcaps(s):
        return s.upper()
    ","Text"];
    session=StartExternalSession["Python"];
    ExternalEvaluate[session,File[script]];
  2. To test the Node.js connection a bit of code from doc section. Starting a server on port 8070.

    webServerSession=StartExternalSession["NodeJS"->"String"];
    ExternalEvaluate[webServerSession,"var http = require('http'); var url = require('url');"];
    ExternalEvaluate[webServerSession,"var res = http.createServer(function (req, res) {
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Date from Node.js server on 8070 inside docker:  '+url.parse(req.url,true).query.time);
    }).listen(8070);"];
  3. Now a small greetings service using the new SocketListen functionality of 11.3.

    image=ImageCollage[{Import["https://i.stack.imgur.com/EhQlR.png"],GeoImage[Here,"StreetMap"]}];
    listener=SocketListen[8080,Function[{assoc},
    With[{client=assoc["SourceSocket"]},
    WriteString[client,
    	ExportString[
    	HTTPResponse@
    	TemplateApply[XMLTemplate["<h1><wolfram:slot id=1/></h1><wolfram:slot id=2/><h5><wolfram:slot id=3/></h5><h5><wolfram:slot id=4/></h5><wolfram:slot id=5/>"],
    	{"A Docker Hello from the Wolfram Language \[HappySmiley]️\[HappySmiley]️\n",
    	"<body>Today's date is :  "<>DateString[]<>"</body>"<>"<h2>You are here with docker! </h2>",
    	"Reverse capitalized date from python inside docker : "<>ExternalEvaluate[session,"stringallcaps(stringreverse('"<>DateString[]<>"'))"<>"\n"],
    	URLRead[URLBuild["localhost:8070",<|"time"->DateString[]|>],"Body"],
    	image }]
    	,
    	"HTTPResponse"
    	]
    	];
    Close[client]
    ]
    ]
    ]
  4. Save the above code in a file hello.wl anywhere in your /home folder as we have mounted it in our docker run command.

  5. Going back to the console of the docker we can cd to the /mma directory and navigate to the directory in the host where we have saved the above Mathematica code as hello.wl. Now in the docker console we can run wolfram and load the hello.wl file.

    <<hello.wl

    1526917324800

  6. Now just open http://127.0.0.1:8080 and you will be greeted with something cool 🏄 from your docker container. It is a web page served by the Wolfram Mathematica from within your docker container.

Final outcome!

Formatting of this post might be a bit crazy as I wrote it in a .md file editor and pasted here.

1526917635091

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.