Skip to content
ElectricalBoy edited this page Jun 15, 2022 · 7 revisions

Welcome to the Containernet Wiki.

Container Requirements

Containers that should be executed within Containernet should fulfill the following requirements:

  • bash installed (for Alpine Linux based images, apk add bash)
  • ip installed (e.g., Ubuntu iproute package)
  • ping installed (e.g., Ubuntu iputils-ping package)
  • The main entry point script must not block the shell.

The CMD field in the Dockerfile is ignored. The container will by default execute /bin/bash. You can overwrite this by passing dcmd="..." when adding a container to the network. Do this if you need to start a process (eg. dcmd="python server.py").

An example Dockerfile to build a alpine:latest, compatible container:

FROM alpine:latest
  
RUN apk add --update --no-cache \
        bash \
        tcpdump \
        iperf \
        busybox-extras \
        iproute2 \
        iputils

CMD /bin/bash

Tested Images

There are plenty example Dockerfiles for different base images that are compatible with Containernet. The compatibility of the containers is checked with this script.

The following base images have been tested with Containernet:

name status additional packages required
ubuntu:trusty works
ubuntu:xenial works net-tools, iproute, iputils-ping
ubuntu:bionic works net-tools, iproute2, iputils-ping
ubuntu:focal works net-tools, iproute2, iputils-ping
centos:6 deprecated (EOL) net-tools, iputils
centos:7 works net-tools, iputils-ping
centos:stream8 works net-tools, iproute, iputils
cirros:latest incompatible (bash missing)

We are always looking for example container images that use other base images, e.g., other distributions or versions. To test and contribute your example container image, follow these steps:

  1. Create Dockerfile.distro.version in this folder.
  2. Extend your Dockerfile to automatically install everything needed to make the created image compatible to Containernet, e.g., install net-tools, iproute, iputils-ping. The Dockerfile has to end with CMD /bin/bash.
  3. Add your Dockerfile to build.sh and run it.
  4. Add your Dockerfile to the test topology containernet_container_test.py (addDocker, addLink, net.ping).
  5. Run sudo python containernet_container_test.py to finally check your image.
  6. Create a PR with your changes.

Exposing and mapping ports

You can simply expose and map network ports to the host machine using Docker's management network. The format to pass port bindings is opposite to that of the Docker CLI. For example, to open the container port 80 and map it to the host port 3000, you should use:

d1 = net.addDocker(dimage="ubuntu:trusty",
                   ports=[80],
                   port_bindings={80: 3000})

The ports parameter tells Docker to open port 80 of the container and the port_bindings parameter provides the actual mapping.

For more granular options such as specifying the port protocol, refer to the corresponding section in the Docker SDK for Python reference.

Passing environment variables

You can simply pass a dict of environment variables:

d1 = net.addDocker("d1", 
                   dimage="ubuntu:trusty”,
                   environment={"var1": "value1", "var2": 5})

Adding shared volumes

Shared volumes are added the same way as with the normal Docker CLI:

d1 = net.addDocker("d1",
                   dimage="ubuntu:trusty",
                   volumes=["/host/directory:/container/directory”)

Manually setting MAC and IP addresses

You can specify IP and MAC addresses for the default interface of a container like this:

d2 = net.addDocker("d2", ip="10.0.0.252", mac="00:00:00:00:00:02", dimage="ubuntu:trusty")

If you want to assign them to a specific interface, use the following syntax:

net.addLink(d1, s2, params1={"ip": "192.168.1.1/24"}, addr1="00:00:00:00:00:01”)

Limiting the maximum memory

To set the maximum memory the container can consume to 512mb and the maximum memory he can swap to disk to 1024mb, use:

d1 = net.addDocker("d1", 
                   dimage="ubuntu:trusty”,
                   mem_limit="512m", 
                   memswap_limit="1536m")

For more details refer to the Docker reference on memory limits.

Setting IPC or devices properties

See this example.

d1 = net.addDocker("d1", 
                   dimage="ubuntu:trusty",
                   ipc_mode="shareable",
                   devices=["/dev/net/tun"])  # share IPC
d2 = net.addDocker("d2",
                   dimage="ubuntu:trusty",
                   ipc_mode="container:mn.d1",
                   devices=["/dev/net/tun"])  # use IPC of other container

API

Method Containernet.addDocker

argument Description Type Default Possible Values
name hostname of the container str No default, Argument is required
ip IP of the default inteface hostname-eth0 str '10.0.0.0' and counting up after every function call e. g. "10.0.0.251"
mac mac address of the default inteface str does not exist, see below e. g.
"00:00:00:00:00:01"
cores str does not exist, see below
dcmd containers CMD command str "/bin/bash" e. g.
"python run_server.py"
dimage Docker image str No default, Argument is required tag or image ID
cpu_quota Limit CPU CFS (Completely Fair Scheduler) quota int -1
cpu_period Limit CPU CFS (Completely Fair Scheduler) period int None
cpu_shares CPU shares (relative weight) int None
cpuset_cpus CPUs in which to allow execution str None
mem_limit Memory limit str or int None
memswap_limit Total memory (memory + swap), -1 to str or int None
environment Set environment variables dict {} {"var1": "value1", "var2": 5}
storage_opt Storage driver options for the container (require storage drivers) dict {} {"size": "2G"}
volumes See Docker: Volumes and CN-Wiki: Getting Started: Volumes. list of strs [] e. g. ["/home/user1/:/mnt/vol2:rw"], ["volume1:/mnt/vol2:rw"]
tmpfs Temporary filesystems to mount, as a dictionary mapping a path inside the container to options for that path list [] e. g. ["/home/vol1/:size=3G,uid=1000"]
network_mode -bridge Create a new network stack for the container on the bridge network.
- none No networking for this container.
- container:<name|id> Reuse another container's network stack.
- host Use the host network stack.
str None bridge,
none,
container:<name|id> and
host
publish_all_ports Publish all ports to the host. bool True True or False
port_bindings key-value-pair represents a containers outer port binded to a port inside dictionary {} - no port_bindings e. g. {80: 8000, 5001:5001}
ports port numbers to use list of integers [] - no ports e. g. [80, 5001]
dns Set custom DNS servers. list []
ipc_mode Set the IPC mode for the container. str None See Docker Reference.
devices Expose host devices to the container, as a list of strings in the form <path_on_host>:<path_in_container>:<cgroup_permissions>. list [] See Docker Reference.
cap_add Add kernel capabilities. list [] e.g. ["sys_admin", "mknod"]
sysctls Kernel parameters to set in the container. dict {}  See Docker Reference.
build_params Passed to build function of the Docker-Low-level-API. Any parameters of that function can be set in this dict. See https://docker-py.readthedocs.io/en/stable/api.html#module-docker.api.build dict {} {"dockerfile": "Dockerfile.server", <br> "path": example_containers/image1/}

Note for arguments mac and cores:

  • macs can be set automaticaly, if Containernet_obj.autoSetMacs == True (which is by default False). Otherwise attribute does not exist if not set explitcitly
  • cores can be set automaticaly, if Containernet_obj.autoPinCpus == True (which is by default False). Otherwise attribute does not exist

Note for argument build_params:

  • if "path" is not set build_params will be ignored, as it is not set
  • build_params["tag"] is not set, it is set to dimage
  • in current version it works only with tags, not with image IDs, so either dimage or build_params["tag"] must be set, otherwise an error will be raised
  • build_params["tag"] overwrites dimage
  • if the Dockerfile is not named just Dockerfile, build_params["dockerfile"] must be set

Other methods

Please see the Mininet Documentation for information on addLink, addSwitch and other methods.