Managing Docker Containers#

For some use cases, a remote Docker container can be seen as a special Host. EnOSlib provides a DockerHost abstraction that helps in controlling remote Docker Containers.

Advanced usage#

 1"""
 2Example that makes use of the DockerHost data structure.
 3
 4This is an advanced example where
 5- docker containers will be started on g5k machines
 6- network emulation will be enforced between those docker containers by
 7reusing |enoslib| api functions.
 8"""
 9import logging
10from pathlib import Path
11
12import enoslib as en
13
14en.init_logging(level=logging.INFO)
15en.check()
16
17job_name = Path(__file__).name
18
19
20conf = (
21    en.G5kConf.from_settings(job_name=job_name, walltime="0:30:00", job_type=[])
22    .add_machine(roles=["control"], cluster="ecotype", nodes=2)
23    .finalize()
24)
25
26provider = en.G5k(conf)
27
28# Get actual resources
29roles, networks = provider.init()
30
31# Install docker
32registry_opts = dict(type="external", ip="docker-cache.grid5000.fr", port=80)
33d = en.Docker(
34    agent=roles["control"], bind_var_docker="/tmp/docker", registry_opts=registry_opts
35)
36d.deploy()
37
38# Start N containers on each G5K host (for a total of 2*N containers)
39N = 4
40with en.play_on(roles=roles) as p:
41    p.raw("modprobe ifb")
42    for i in range(N):
43        p.docker_container(
44            name=f"mydocker-{i}",
45            image="ubuntu",
46            state="started",
47            command="sleep 10d",
48            capabilities=["NET_ADMIN"],
49        )
50
51# Get all the docker containers running on all remote hosts
52dockers = en.get_dockers(roles=roles)
53
54# Build the network contraints to apply on the remote docker
55# We assume here the interface name in docker to be eth0
56sources = []
57for idx, host in enumerate(dockers):
58    delay = idx
59    print(f"{host.alias} <-> {delay}ms")
60    inbound = en.NetemOutConstraint(device="eth0", options=f"delay {delay}ms")
61    outbound = en.NetemInConstraint(device="eth0", options=f"delay {delay}ms")
62    sources.append(en.NetemInOutSource(host, constraints={inbound, outbound}))
63
64# This requires the Docker client to be installed on the local machine.
65# Also, it might not work well because SSH connections are handled by Docker.
66# See https://gitlab.inria.fr/discovery/enoslib/-/issues/163 for discussion
67with en.play_on(roles=dockers, gather_facts=False) as p:
68    # We can't use the 'apt' module because python is not installed in containers
69    p.raw("apt update && DEBIAN_FRONTEND=noninteractive apt install -qq -y iproute2")
70
71en.netem(sources)