The security of containers is acheived by enhancing the level of isolation, a such concept that exists clearly with virtual machines since it is running under hypervisor.

Nabla brings a new approach for container isolation. The isolation β€œcomes from limiting access to the host kernel via the blocking of system calls. β€œ[1]

The approach is well detailed in the official website.

Nevertheless, this is the architecture of Nabla container:

Nabla container internals


  • Vagrant (+ Virtualbox), then:
git clone && cd hello-nabla-container;
vagrant up;
  • Or in general, you could take the script scripts/ and run it on Ubuntu machine.

Provision the machine

Install dependencies

  • Install docker-ce
apt-get -yq update
apt-get -y upgrade
# Install docker community edition
apt-get remove docker docker-engine -y;

apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common -y

curl -fsSL | apt-key add -

add-apt-repository \
    "deb [arch=amd64] \
    $(lsb_release -cs) \

apt-get update -y && apt-get upgrade -y;
apt-get install -y docker-ce;
  • Install Go
cd /tmp
curl -O
tar -xvf go1.10.3.linux-amd64.tar.gz
mv go /usr/local
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go

Install NABLA runtime

The official website explains how to setup NABLA, however, it does NOT leverage the systemd module of the modern linux systems. That’s why, I didn’t follow the same approach (/etc/docker/daemon.json), instead, I leveraged systemd.

# download "runnc" source code
go get
cd ${GOPATH}/src/

# build the binary "runnc" and other binaries needed
make container-build

# Validate the Build
ls -lh build/{nabla-run,runnc,runnc-cont}

# Install "runnc"
cd ${GOPATH}/src/
make container-install

# Validate the Install
ls -lh /usr/local/bin/{nabla-run,runnc,runnc-cont}
ls -lh /opt/runnc/lib/{,,}

# Configure NABLA runtime with docker
apt-get install -y genisoimage
mkdir -p /etc/systemd/system/docker.service.d/
cat > /etc/systemd/system/docker.service.d/nabla-containers.conf <<EOF
ExecStart=/usr/bin/dockerd -D --add-runtime nabla-runtime=/usr/local/bin/runnc
systemctl daemon-reload
systemctl restart docker
docker run hello-world

If you want to make Nabla as the default runtime and avoid specifying the argument --runtime=nabla-runtime with each docker run, you may need to replace:

ExecStart=/usr/bin/dockerd -D --add-runtime nabla-runtime=/usr/local/bin/runnc


ExecStart=/usr/bin/dockerd -D --add-runtime nabla-runtime=/usr/local/bin/runnc --default-runtime=nabla-runtime

Now, it is time to bake this machine and consider it as image (box) to spin up other duplicated machines with Nabla Runtime; successfully installed and configured.

Run a demo : Node application running inside Nabla container

Download the application

export GOPATH=$HOME/go
go get

Take a look at the code of this Node application, namely:

As you may note:

  • The base docker images (.i.e: FROM nablact/nabla-node-base) are baked in nabla-base-build repository.

  • All those base images define ENTRYPOINT *.nabla as the last layer of its Dockerfile.

  • The image of the main container should be built from one of nabla base images, however, you are still able to use community images for non-main containers by leveraging the multi-stage builds.

Build the docker image for the node application

cd ${GOPATH}/src/
docker build -t node-express-nabla -f Dockerfile.nabla .
# Validate the build
docker images | grep node-express-nabla

Run the demo

# Run the demo - run it in background with "-t -d"
docker run --rm -t -d --runtime=nabla-runtime -p 9090:8080 node-express-nabla

We reached the moment of truth:

curl -s http://localhost:9090
# Hello Nabla from !

To understand more the stdout of the last command, take a look again at :


Since it is possible to set the default runtime of docker to be NABLA, thus, it is possible to have a Kubernetes cluster with nodes (workers) with NABLA as default container runtime.

Then, label those nodes with a specific label:

# containerRuntime=nabla
kubectl label nodes containerRuntime=nabla

After that, you can assign/schedule pods to those nodes by using the nodeSelector property.

apiVersion: v1
kind: Pod
  name: demo-node-express-nabla
    - name: demo-node-express-nabla
      image: "node-express-nabla"
    containerRuntime: nabla