The safest place to try a network change is not the production network. ContainerLab lets you describe a topology in a short text file, spin a whole network up on a laptop in seconds, break it, fix it, and throw it away. It is the tool we reach for whenever a change is too risky to test in production, which in critical networks is most of them.
This is a getting-started guide. By the end you will know what ContainerLab is, what a lab file looks like, the four commands that run the whole lifecycle, and how we use it to build a digital twin of a real network with MikroTik and OT gear. If you would rather click than read, our OT security lab runs in a browser and you can follow along.
What ContainerLab is
ContainerLab is an open-source tool that runs network labs based on containers. You write a topology file, it starts the nodes, wires them together with virtual cabling, and manages their lifecycle. Because the nodes are just containers, a lab starts in seconds and costs you nothing when it is not running.
It distinguishes three kinds of nodes. Containerised network operating systems run natively. Traditional VM-based systems can be containerised through the vrnetlab integration. And any Linux container can join in, which is how you add hosts, servers, attackers or, in our case, simulated PLCs.
Text-based
The whole topology is one YAML file you can read, diff and check into Git. The lab is the file.
Reproducible
Anyone who clones the repo gets the exact same network. No snowflake VMs, no "works on my machine".
Disposable
One command up, one command down. Break things on purpose, then start clean in seconds.
The shape of a lab
A lab is a .clab.yml file. It has a name, a set of nodes, and the links between them. Each node has a kind that tells ContainerLab how to run it. Here is a trimmed version of one of our own labs: a MikroTik firewall and switch, plus a simulated PLC as a Linux container.
ot-sec-segmented.clab.yml
# a network, described oncename: ot-sec-segmented
mgmt:network: ot-sec-segmented
ipv4-subnet:192.168.100.0/24topology:defaults:kind: mikrotik_ros # MikroTik RouterOS, via vrnetlabimage:vrnetlab/mikrotik_routeros:7.20nodes:gw-firewall:# the segmentation gatewaymgmt-ipv4:192.168.100.11startup-config:configs/gw-firewall.rscsw-dist:mgmt-ipv4:192.168.100.12wago-plc2a:# a PLC, as a Linux containerkind: linux
image:ghcr.io/narrowin/ot-sec-lab-plc:latestlinks:# virtual cabling between node interfaces
- endpoints: ["gw-firewall:eth1", "sw-dist:eth1"]
- endpoints: ["sw-dist:eth2", "wago-plc2a:eth1"]
That is the whole idea. The nodes are your devices, the links are the cables, and kind is the only bit of magic: it lets a Nokia, an Arista, a Cisco, a MikroTik and a plain Linux box all sit in the same file and behave like the real thing. The example here uses MikroTik because it is what a lot of our work runs on, but ContainerLab supports a long catalogue of kinds, from Nokia, Arista, Cisco and Juniper to firewalls like Fortinet and Palo Alto.
Four commands, the whole lifecycle
Once the file exists, you barely need to remember anything. Install once, then deploy, look, connect, and destroy.
the full loop
# install ContainerLab (one line, RHEL or Debian based)
curl -sL https://containerlab.dev/setup | sudo -E bash -s "all"# bring the lab up
clab deploy -t ot-sec-segmented.clab.yml
# see what is running: names, kinds, management IPs
clab inspect -t ot-sec-segmented.clab.yml
# jump onto a node, it is just SSH
ssh admin@192.168.100.11
# tear the whole thing down, leave nothing behind
clab destroy -t ot-sec-segmented.clab.yml
ContainerLab adds the nodes to your /etc/hosts, so you can also reach them by name, like ssh admin@clab-ot-sec-segmented-gw-firewall.
Worth knowing early
A few things that make ContainerLab pleasant to learn on, beyond the four commands.
Add latency, jitter or packet loss to a link with netem, to see how a design behaves on a bad day, not just a perfect one.
Why we build on it: the digital twin
In a critical network you cannot test a firewall change, a segmentation redesign or a firmware roll-out by trying it on the live plant. So we build a digital twin: a faithful copy of the real network, running in ContainerLab, that we can plan against, test on, and validate before a single change touches production.
01
Plan
Model the target network as a topology file. The design is now something you can run, not just a diagram.
02
Test
Deploy the twin, apply the change, break it on purpose. Failures happen here, where they are free.
03
Deploy
Roll the proven configuration out to the real devices, with the same automation you tested in the lab.
04
Validate
Compare the real network back against the twin, and keep the two in sync as the source of truth.
In a critical network, you don't get to experiment on the live plant. So we build a digital twin, make our mistakes there, and only deploy what we have already proven.
Tomáš Horyl, Senior Network & Security Engineer, narrowin
Tomáš Horyl · Building digital twins with MikroTik CHR, ContainerLab and Ansible
Bringing in VM-based devices
Many network operating systems, Cisco, Juniper, Palo Alto and others are provided as virtual machines. ContainerLab handles that through vrnetlab, which packages a VM as container and by this it behaves like any other node in the topology. MikroTik is our worked example here because plenty of our work runs on it, and the mikrotik_ros kind in the file above is exactly this in action.
One thing worth knowing: ContainerLab uses its own advanced fork of the original vrnetlab (srl-labs/vrnetlab). Images built with the upstream project will not work, so build from the fork.
With the MikroTik nodes running, we drive their configuration the same way we drive the real boxes: with Ansible. RouterOS has no Python interpreter, so we use the community.routeros modules over the API for structured, idempotent changes. That is the bridge between the twin and production, and it is open: our ansible-mikrotik collection is the same one we use on customer networks.
A real example: the OT security lab
To make this concrete, we maintain a full OT network security lab in ContainerLab, built together with SWITCH. It is a realistic industrial network: MikroTik firewall and switches, and simulated PLCs from WAGO, Bosch Rexroth, Schneider and ABB running a Codesys runtime, laid out across VLAN zones for hygiene, process, disposal and a control room.
It ships in two shapes from the same repo. A flat topology, the insecure baseline where everything can talk to everything, and a segmented topology with proper zones and a firewall between them. Swapping one for the other is a one-word change on the command line, which makes the value of segmentation something you can demonstrate rather than describe.
flat vs segmented, same lab
clab deploy -t ot-sec-flat.clab.yml # everything can reach everything
clab deploy -t ot-sec-segmented.clab.yml # zones, VLANs and a firewall
On top of the lab sits a set of hands-on exercises: VLAN discovery and traffic analysis, an ARP spoofing attack, spanning-tree behaviour, and more. Because the whole thing runs in GitHub Codespaces, a participant needs nothing but a browser to get a real, riggable network in front of them. This lab is the backbone of our OT security courses.
How to start, today
Two paths, depending on whether you want to install anything.
A
The no-install path
Open our Mikrotik-ansible lab in GitHub Codespaces and wait a few minutes for it to build. You get a full network in the browser, no Docker/Podman on your machine. Then run clab deploy -t mikrotik.clab.yml and you are in.
B
The local path
On any machine running Docker/Podman (Windows WSL, macOS, Linux), install with the one-liner above, grab a topology from the examples or write your own, and clab deploy. Start with two nodes and one link, then grow it.
C
Just try it
Deploy, connect to a node, change something, and clab destroy. The first time you rebuild a "broken" lab in ten seconds, the test-before-deploy habit tends to stick.
Beyond the intro
A digital twin of your network
Building a twin of a real, messy network is more involved than a two-node example: capturing the topology, getting the right images, and wiring up the automation that keeps the twin and production in sync. That is work we do with customers.
How is ContainerLab different from GNS3 or EVE-NG?
All three build virtual network labs, but ContainerLab is container-first and file-driven. The lab is a text file you check into Git, it starts in seconds because most nodes are containers rather than full VMs, and it fits cleanly into automation and CI pipelines. VM-based routers still run when you need them, through vrnetlab, so you do not lose the heavy devices. The trade-off is that it is CLI-driven by nature, though the VS Code extension adds a visual layer.
Do I need powerful hardware?
For containerised nodes and Linux hosts, no. A laptop runs a sizeable lab comfortably. VM-based nodes like MikroTik CHR cost more memory each, so a large twin of VM routers needs a real server. A good rule: prototype small on your machine, run the full twin on a lab server.
Can I run MikroTik, Cisco or Nokia in the same lab?
Yes. That is the point of kinds. Containerised systems like Nokia SR Linux run natively, and VM-based systems like MikroTik RouterOS, Cisco and Juniper run through vrnetlab, all in one topology file. You can mix vendors freely and add plain Linux hosts alongside them.
Is ContainerLab production tooling or just for learning?
Both. It is excellent for teaching, which is why our courses run on it, but the same reproducibility makes it a serious pre-production tool: validating segmentation designs, rehearsing firmware upgrades and testing automation against a twin before any of it reaches the live network.