Demystifying DOCKER – II : The FEniCS Workflow
- Post by: Philip Luke K
- May 6, 2021
- No Comment
Part I : Demystifying DOCKER – I : The What and How
Now that the idea and use of docker is clear, and that docker is installed and running; let us see how to make use of it to run FEniCS based codes in your system.
FEniCS is a popular open-source computing platform for solving partial differential equations (PDEs). FEniCS enables users to quickly translate scientific models into efficient finite element code. It has a Python front-end and a C++ backend
As already discussed in Part 1, the first thing that you need to run docker is to have a dockerfile. Now you can either use existing dockerfiles or you can create one of your own. This post will use and apply the dockerfile available in this repository. This dockerfile consists of all the libraries and dependencies to run FEniCS and carry out research work in our Computational Mechanics Lab at IIT Roorkee. This is our lab-specific updated dockerfile written over the official dockerfile of DOLFIX-X. When the docker image is built, this will install FEniCS in an Ubuntu environment. So even if you are using Windows or macOS as your original OS, you will be able to work in FEniCS in Ubuntu through the docker.
If you are someone interested in doing simulations in the areas of Finite Element Methods, Topology Optimization, Phase Field Fracture, or Isogeometric Analysis, you can also use utilize our dockerfile in the public domain.
FEniCS via Command Line Interface
Docker Build
Once the docker is installed and running, open your command-line interface/terminal (I prefer CMDER), go to the folder containing the dockerfile and execute
docker build --target base -t fenics .
This command will build the container in your terminal. Let us deconstruct the code
docker build
: build an image from a dockerfile
—target base
: when you need only specific part of the dockerfile to be built. building stops at the stage named base in the dockerfile.
-t fenics
: tags the docker image with the name fenics.
.
: tells the docker to look for the dockerfile in the current directory
From the specifications of our dockerfile, this build command will install FEniCS in an Ubuntu environment (Guest-OS) which we will be able to access via docker virtualization.
Docker Run
So the build has enabled a docker image. Now we need to write/edit/run the code written in the FEniCS language. i.e we need to access the FEniCS environment. For that use docker run in the terminal to kick-start our container which we tagged fenics. Suppose my code is saved in the directory D:\codes
docker run -v D:\codes:/root/ -w /root/ -it fenics
docker run
: run a command in a new container
-v D:\codes:/root/
: This portion of the code requires a bit more explanation. As already mentioned before, the docker build command has installed FEniCS in Ubuntu and we can access this Ubuntu via docker. In the docker run command, we are in fact trying to set up a connection between the host system and ubuntu. So all the FEniCS work is actually done inside Ubuntu (Virtual OS) now and thus we need to follow the directory structure of Ubuntu. But our code is inside D:\codes which is a part of the Host OS (your Windows/MacOS). The -v
command is basically used to mount a volume to the container. Using this, we mount our host system directory (D:\codes) to the /root directory present in Ubuntu. We could thus see all of the files/folders present in D:/Codes in the /root directory inside the container.
-w /root/
: sets the working directory. lets the command being executed inside the root directory
-it
: run a container in interactive mode. This means you can execute commands inside the container (via terminal) while it is still running.
fenics
: asking to use the image with the tag ‘fenics’
Once after the run command is executed, you will be able to run your application (FEniCS here). The run code above is customizable according to the user’s needs. At this point, if you open your docker-desktop, you will see something like this.
The green color means that your docker image is up-and-running. The name nice_bell is completely arbitrary and changes with computer and each run. But you can notice the tag fenics which was used to build this container.
FEniCS via Jupyter Notebook
As mentioned, the front-end of FEniCS is in Python. This basically means that python commands are used to write and execute codes in FEniCS. Now the most convenient way to write Python code is to use the interactive and live environment, Jupyter Notebook, which helps you correct and validate your code on-the-go. One thing to know before reading further is that the default URL of the jupyter web application is http://localhost:8888
To write FEniCS based code in Jupyter Notebook, you have to build docker containers as we did for command line interface as above. This follows almost the same procedure and execution as above.
Docker Build
Once the docker is installed and running, open your command-line interface/terminal, go to the folder containing the dockerfile and execute
docker build --target notebook -t fenics_notebook .
This command will build the container in your terminal. Let us deconstruct the code
docker build
: build an image from a dockerfile
—target notebook
: building stops at the stage named notebook in the dockerfile
-t fenics_notebook
: tags the docker image with the name fenics_notebook.
.
: tells the docker to look for the dockerfile in the current directory
Docker Run
So this has enabled a docker image tagged fenics_notbook. Now we need to open a Jupyter Notebook page in our webpage using a local web address. For that use docker run in the terminal to kick-start our container which we tagged fenics_notebook. Suppose my code is saved in the directory D:\codes
docker run -p 8888:8888 -v D:\codes:/root/ -w /root/ fenics_notebook
docker run
: run a command in a new container
-p 8888:8888
: to allow external connections (jupyter notebook) to the container. In this docker run, we are setting up a connection between the host system and ubuntu and are trying to access data from ubuntu in our host system when using jupyter notebook (an external connection). The -p
command allows external connections to the container. Both the host (windows) and guest (Ubuntu) systems need to be bound to jupyter port.
We wish to transfer some information from the container system to the host system. For that, we need to connect both the system via some kind of digital wire. Every system has multiple ports from where the information can go out and come inside. Here we are saying that attach my digital wire that will transfer the data at port 8888 on the host system and at 8888 on the container system
-v D:\codes:/root/
: mounts the directories D:\codes and /root/ into the container. D:\codes is where your data will be saved. /root/ is where that data will be located inside the container. We mount our host system directory (D:\codes) to the /root directory present in Ubuntu. We could thus see all of the files/folders present in D:/Codes in the /root directory inside the container.
-w /root/
: sets the working directory. lets the command being executed inside the root directory
fenics_notebook
: asking to use the image with the tag ‘fenics_notebook’
No need of an interactive shell/terminal here as we are directly executing in the jupyter notebook. Once the run command is executed, you will be able to see a train of executions in your terminal like this.
To open jupyter notebook, copy and paste any of the links given in the highlighted area and run in your web browser. Most commonly, the last link will be the right one. If you happen to open your docker-desktop now, you will see another up-and-running with any arbitrary name and the tag fenics_notebook.
Killing Docker
The docker container keeps on running in the background till the system is switched off or the container is killed off manually. A container running in the background actually does little harm, as it is very light-weight and smooth. But sometimes for troubleshooting purposes, we might need to kill off the container(s). To do this, open a fresh terminal/cmder log and type
docker ps
This command will list all the currently running containers in the system with their container_id and other details as shown below.
Above figure shows a docker where only one container is running. There might be cases when multiple containers will be running. This unique container id is what we require to kill off a particular container. For that use the command
docker kill container_id
This will let you kill the container
Now if you open the docker desktop, you will see that the container has exited.