Core and Docker Together at Last

Docker on Core 4.7

In this article I will cover how we get the power of Docker to combine with the simulated network of CORE. I assume that you are familiar with CORE if not read the docs.

I have written about CORE before here Common Open Research Emulator (CORE). It is an excellent tool for network modelling. I intend to use it for a Doctoral project which will be testing a new protocol in harsh conditions. I wanted an easy way to wrap and deploy my software and have been looking in to Docker. It is quite like Virtual Machines but more lightweight. It allows containers to be produced that give a fixed infrastructure and can be moved between machines easily. It occurred to me that this could be helpful to deploy on nodes of a CORE simulation.

First you need to install Docker on your host machine. Instructions are here https://docs.docker.com/installation/#installation 

Once you are up and running you should familiarise yourself with Docker through the excellent documentation. The tutorial is also a good place to get a quick overview and should be enough for you to follow on here.

Once you are ready to proceed then we need to add a new service to CORE. This is done by placing a python file in the ~/.core/myservices folder. The file is here

You need to change this line in the existing __init__.py

""myservices

Custom services that you define can be put in this directory.  Everything
listed in __all__ is automatically loaded when you add this directory to the
custom_services_dir = '/full/path/to/here' core.conf file option.
"""
__all__ = ["sample", "docker"]

Here I have added "docker" in to the __all__ variable array.

I also need to ensure that Core loads these services by adding a 'custom_services_dir = /home/username/.core/myservices' entry to the /etc/core/core.conf file. Where username is swapped for your own.

With that done you can restart the core-daemon and this new service will be available within the nodes.

The new Docker Service
The new Docker Service

When you run the simulation and go to the terminal of a node with the docker service then you can run standard docker commands. For instance you can see what images are available:

root@Docker:/tmp/pycore.34206/Docker.conf# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
mysql               5                   a950533b3019        3 days ago          235.6 MB
mysql               5.6                 a950533b3019        3 days ago          235.6 MB
mysql               5.6.20              a950533b3019        3 days ago          235.6 MB
mysql               latest              a950533b3019        3 days ago          235.6 MB
mysql               5.7                 77ef40ef4fa6        3 days ago          252.2 MB
mysql               5.7.4               77ef40ef4fa6        3 days ago          252.2 MB
mysql               5.7.4-m14           77ef40ef4fa6        3 days ago          252.2 MB
mysql               5.6.17              36e732ca2610        9 weeks ago         458.7 MB
training/webapp     latest              31fa814ba25a        12 weeks ago        278.8 MB
root@Docker:/tmp/pycore.34206/Docker.conf# 

In this case I have some mysql images and a training app I had for learning Docker. I want the ability to run some python code within my docker so lets get a python image. Within a host shell try this:

stuart@mainPC:~/.core/myservices$ sudo docker pull python
Pulling repository python
a87a2288ce78: Download complete 
f9014fefee22: Download complete 
1c8df2f0c10b: Download complete 
511136ea3c5a: Download complete 
1e8abad02296: Download complete 
f106b5d7508a: Download complete 
0ae4b97648db: Download complete 
a2df34bb17f4: Download complete 
17384445ddf7: Download complete 
8099436dc35e: Download complete 
30a4670e4cf6: Download complete 
66c7a13c1296: Download complete 
e4c85c8c5298: Download complete 
ee302d4ff929: Download complete 
652d45419450: Download complete 
9d97f9202188: Download complete 
5bebb6ca276b: Download complete 
911d86408216: Download complete 
bd4e6b205531: Download complete 
239aea06dee9: Download complete 
b00c98ab9d6c: Download complete 
ed2b129b38e9: Download complete 
40f67fed3eec: Download complete 

It will take some time and load a lot of images. This is going to the internet so should be done on the host not within a running node. If you stop and restart the simulation and then look at the docker images you will see we have a lot of python related ones now.

We can now make use of them by running within a node.

docker run -i -t python /bin/bash

This places you within the container and you can run python for instance in there. Well so far so pointless as you could have equally run python within the node itself which would have just used the hosts version. But the point of using a Docker container is you know it is exactly the same if you use that container on this machine or any other.

We can get more usefulness thought by making our own container based on the python one. 

On the host lets enter the python image and add a simple app. When you exit you will get a long id again. Copy this so we can commit later.

sudo docker run -t -i python /bin/bash 
mkdir /apps 
cd /apps
echo "print('Hello world')">hello.py
exit

This just adds a directory and put the simplest possible python program in it. In order to save this as an image to use you must do a commit:

sudo docker commit -m="Added hello world" -a="Stuart Marsden" 49db49894a92 core/hello:v1

This makes a new image called core/hello with a tag of v1. You need to change the id to be what you noted earlier. This can now be run from a node by doing:

docker run -d core/hello:v1 python /apps/hello.py

This does not show the output but gives a big long id string. You can see the output by running 'docker logs' and the first few letters of the id that just returned. You can then see that it ran and returned Hello World. Still not very exciting.

What about setting up a python web server. Within a node that has docker running do this:

docker run -it -p 8000:8000 python /bin/bash
python3 -m http.server

This will start serving whatever directory is current in the docker container. The -p 8000:8000 just maps the port 8000 within the container to port 8000 outside. We then go to another node and try 'curl 10.0.0.1' or whatever the IP of the docker node is. This should show you that it is serving.

Future Steps

This just scratches the surface of what the combination of CORE and Docker could do. There are many images on the Docker website which include many network applications that you may want to test on a simulated network. It also allows uploads so we could share useful containers for CORE.

You will have noted that Docker abstracts the network which is already abstracted by CORE. This is a bit pointless but the version that is easily installed with Ubuntu cannot avoid this. The latest version though has the ability for a container to run on the host network. As fas as Docker should be concerned this is the already abstracted core network interface. I will try this when I have a chance. I have also had a few issues with Multicast but I need to look at it a bit more (may be TTL issues through the container network).

It would be nice to have a GUI that would allow the selection of a Docker image. The added service just starts Docker and you either have to add something to the startup config for each node or go in to the terminal and do it by hand. If there is interest I could see if the CORE GUI could be extended to allow easy selection of an image per node.

In the meantime I suggest that people read up on Docker. Please leave comments below and we can look at getting the integration better.

Tags in this Article:  Simulation CORE Docker