joker

Docker images for Julia based on the official Ubuntu minimal build.The images have Julia set as their default entrypoint. Hence, theybehave like Julia binaries. This means that you can easily pass optionssuch as p -4 to the entrypoint just like you would when you installJulia locally.

Some properties

All images are available as automated builds from Docker Hub. You canjust pull them with docker pull brauner/julia anddocker pull brauner/julia3.

The generic Julia images which reside in the julia and julia3folders are compiled with MARCH set to core2 which will make themrun on almost any system. To see how to adapt the image to a specificarchitecture by setting the MARCH flag in Make.user take a look atthe Dockerfiles which reside in the folders which have ivyappended to them. There you can also see how to enable 3D support andvarious other tweaks.

Set up user so that the container does not need to run as root.

Set up /home for user.

Install all recommended Julia dependencies, pull Julia or Julia
0.3 from Github and compile Julia or Julia 0.3 from source.

The Julia binaries reside in /usr/local/bin/julia.

Workflow & Julia Library and Package Management

If you mainly run julia as an ephemeral interactive container andinstall new packages you will need to commit the newly created layer toyour image before you quit in order to have the packages you installavailable via using when you start the container again. To circumventthis I suggest sharing volumes between your julia containers in thefollowing manner:

Create an extremely tiny container from the busybox image exposing afolder .julia with the right permissions which you share via the--volumes-from=DATACONTAINERNAME flag among your julia containers.You will find the Dockerfile for this in the folder jlib andthe image on Docker Hub. You can pull it with docker pull
brauner/jlib.

Run docker run --name=JULIADATA DATACONTAINERNAME true

Run docker run --volumes-from = JULIADATA JULIACONTAINERNAME

Now you can install packages into JULIADATA without having to commit thecontainer as data containers are handled differently by Docker. If youpull a new julia image you can just keep running it with your librariesstill intact. Should a new julia version come out that requiresupgrading all libraries you can just remove your JULIADATA containerwhich will also remove all installed packages and start a new one.

If you still want to install a package ephemerally which gets deletedwhen your julia container exits. You can edit your library path forthe current session.

Graphical Output from Docker Containers

There is a nice and semi-easy way of getting graphical output from aDocker container without having to run an sshd daemon inside of thecontainer. Docker can provide bare metal performance when running a singleprocess which in this case is supposed to be Julia. Running an sshd daemonwill, marginal as it may be, introduce additional overhead. This is notmade better by running the sshd daemon as a child process of thesupervisor daemon. Both can be dispensed with when one makes good use ofbind mounts. After building the image from which the container is supposedto be run we start an interactive container and bind mount the/tmp/.X11-unix folder into it. I will state the complete command andexplain in detail what it does:

docker run -i -t --rm \
# -i sets up an interactive session; -t allocates a pseudo tty; --rm makes
# this container ephemeral
-e DISPLAY=$DISPLAY \
# sets the host display to the local machines display (which will usually
# be :0)
-u chbj \
# -u specify the process should be run by a user (here "chbj") and not by
# root. This step is important (v.i.)!
-v /tmp/.X11-unix:/tmp/.X11-unix \
# - v bind mounts the `X11` socket `/tmp/.X11-unix` into `/tmp/.X11-unix`
# in the container.
--name="jdev" ubuntu-j
# --name="" specify the name of the container (here "jdev"); the image you
# want to run the container from (here "ubuntu-j"); the process you want
# to run in the container (here "Julia").

After issuing this command you should be looking at the beautiful Juliastart output. If you were to try demo(graphics) to see if graphicaloutput is already working you would note that it is not. That is becauseof the Xsecurity extension preventing you from accessing the socket. Youcould now type xhost + on your local machine and try demo(graphics) inyour container again. You should now have graphical output. This methodhowever, is strongly discouraged as you allow access to your xsocket toany remote host you're currently connected to. As long as you're onlyinteracting with single-user systems this might be somehow justifiable butas soon as there are multiple users involved this will be absolutelyunsafe! Hence, you should use a less dangerous method. A good way is touse the server interpreted xhost +si:localuser:username which can beused to specify a single local user (see man xhost). This meansusername should be the name of the user which runs the X11 server onyour local machine and which runs the Docker container. This is also thereason why it is important that you specify a user when running yourcontainer. Last but not least there is always the more complex solution ofusing xauth and .Xauthority files to grant access to the X11 socket(see man xauth). This however will also involve a little more knowledgehow X works.

Entering a running container with docker exec

As of release 1.3. the recommended way of entering a running containeris by using docker exec -it rdev bash (rdev is the name of the runningcontainer and bash the program which is supposed to be run in thecontainer in this example.) which will spawn a new process in the runningcontainer.

Entering a running container with nsenter

Should you need to enter a running container with a new tty you can alsouse nsenter. First find the PID of the (main) process running in thecontainer by either issuing docker top containername or docker inspect
--format {{.State.Pid}} containername. Then use nsenter which shouldusually be installed on your system. If not install it. It can be foundutil-linux (version must be at least 2.23). You can use the commandnsenter --target PID-you-just-found-out --mount --ipc --net --pid or theshort version nsenter -t PID-you-just-found-out -m -i -n -p.