Three years ago I was spinning up GNS3 to test a BGP failover scenario before pushing it to production. The VM took 8 minutes to boot, ate 12 GB of RAM, and crashed twice before I could even ping between routers. That was the moment I started looking for something better — and Containerlab changed everything.
Network engineers and DevOps practitioners both know the lab problem: you need a realistic environment to test against, but standing one up takes forever. Containerlab solves this by defining and deploying multi-vendor network topologies using containers instead of bloated VMs. Full routing protocol support, real vendor OS images, and the whole lab spins up in under 60 seconds.
Quick Start — Up and Running in 5 Minutes
Getting Containerlab running is genuinely fast. You need Docker installed and a Linux host (or WSL2 on Windows).
Install Containerlab
# One-liner install (official script)
bash -c "$(curl -sL https://get.containerlab.dev)"
# Verify installation
clab version
That’s it. No pip, no virtualenv, no dependency hell.
Your First Lab — Three Routers, Two Minutes
Create a file called lab01.yml:
name: first-lab
topology:
nodes:
router1:
kind: linux
image: frrouting/frr:latest
router2:
kind: linux
image: frrouting/frr:latest
router3:
kind: linux
image: frrouting/frr:latest
links:
- endpoints: ["router1:eth1", "router2:eth1"]
- endpoints: ["router2:eth2", "router3:eth1"]
Deploy it:
sudo clab deploy -t lab01.yml
You’ll see the containers spin up and a table showing every node’s management IP. Total time from zero to three connected routers: about 25 seconds on a mid-range laptop.
To connect to router1:
sudo docker exec -it clab-first-lab-router1 vtysh
When you’re done:
sudo clab destroy -t lab01.yml
Containers gone, network interfaces cleaned up, nothing left behind.
Deep Dive — Understanding Containerlab Topology Files
Containerlab’s topology YAML does one job: describe your network. Once you internalize the structure, you can model almost any real-world scenario.
Node Kinds and Images
Containerlab supports several node kinds out of the box:
- linux — any Docker image running Linux (FRRouting, Bird, VyOS)
- srl — Nokia SR Linux (free, full-featured, excellent for labs)
- ceos — Arista cEOS (requires free registration at arista.com)
- crpd — Juniper cRPD (requires Juniper license)
- vr-ros — MikroTik RouterOS via vrnetlab
For most labs without vendor licenses, FRRouting on Linux covers OSPF, BGP, IS-IS, MPLS, and more. Nokia SR Linux is free to pull and gives you a genuine network OS experience.
Configuring Nodes at Deploy Time
Startup configs mount directly into containers via the binds key — no manual copying after deploy:
name: ospf-lab
topology:
nodes:
r1:
kind: linux
image: frrouting/frr:latest
binds:
- configs/r1/frr.conf:/etc/frr/frr.conf
- configs/r1/daemons:/etc/frr/daemons
r2:
kind: linux
image: frrouting/frr:latest
binds:
- configs/r2/frr.conf:/etc/frr/frr.conf
- configs/r2/daemons:/etc/frr/daemons
links:
- endpoints: ["r1:eth1", "r2:eth1"]
mtu: 9000
Your router config lives on the host — version-controlled, diffable, and reproducible across machines.
Network Links and Attributes
Links are veth pairs under the hood. Set MTU, simulate latency, or bridge to a physical host interface — all in the topology file:
links:
# Simple link
- endpoints: ["r1:eth1", "r2:eth1"]
# With impairments (latency simulation)
- endpoints: ["r1:eth2", "r3:eth1"]
mtu: 1500
# Bridge to host physical interface
- endpoints: ["r2:eth3", "host:ens4"]
Advanced Usage — Multi-Vendor BGP Lab
I use this kind of setup to test BGP policy changes before touching production routers. The topology below runs in about 45 seconds on a 4-core machine with 8 GB RAM. GNS3 with equivalent Cisco IOS VMs would need 16 GB minimum.
BGP Lab with FRRouting
name: bgp-lab
topology:
nodes:
isp1:
kind: linux
image: frrouting/frr:latest
binds:
- configs/isp1/frr.conf:/etc/frr/frr.conf
- configs/isp1/daemons:/etc/frr/daemons
isp2:
kind: linux
image: frrouting/frr:latest
binds:
- configs/isp2/frr.conf:/etc/frr/frr.conf
- configs/isp2/daemons:/etc/frr/daemons
customer:
kind: linux
image: frrouting/frr:latest
binds:
- configs/customer/frr.conf:/etc/frr/frr.conf
- configs/customer/daemons:/etc/frr/daemons
client:
kind: linux
image: alpine:latest
links:
- endpoints: ["isp1:eth1", "customer:eth1"]
- endpoints: ["isp2:eth1", "customer:eth2"]
- endpoints: ["customer:eth3", "client:eth0"]
A minimal FRRouting BGP config for the customer router (configs/customer/frr.conf):
frr version 9.0
frr defaults traditional
hostname customer
router bgp 65001
bgp router-id 10.0.0.1
neighbor 10.0.1.1 remote-as 65010
neighbor 10.0.2.1 remote-as 65020
!
address-family ipv4 unicast
network 192.168.100.0/24
neighbor 10.0.1.1 soft-reconfiguration inbound
neighbor 10.0.2.1 soft-reconfiguration inbound
exit-address-family
!
line vty
!
And the daemons file to enable BGP:
bgpd=yes
ospfd=no
zebra=yes
vtysh_enable=yes
Inspecting the Running Lab
# Show all nodes and their management IPs
sudo clab inspect -t bgp-lab.yml
# Connect to customer router vtysh
sudo docker exec -it clab-bgp-lab-customer vtysh
# Inside vtysh — check BGP neighbors
show bgp summary
show ip route bgp
# Capture traffic on eth1
sudo ip netns exec clab-bgp-lab-customer tcpdump -i eth1 -n
Using Nokia SR Linux (Free, No License)
name: srl-lab
topology:
nodes:
leaf1:
kind: srl
image: ghcr.io/nokia/srlinux:latest
leaf2:
kind: srl
image: ghcr.io/nokia/srlinux:latest
spine1:
kind: srl
image: ghcr.io/nokia/srlinux:latest
links:
- endpoints: ["leaf1:e1-1", "spine1:e1-1"]
- endpoints: ["leaf2:e1-1", "spine1:e1-2"]
SR Linux ships with a proper CLI plus gRPC, gNMI, and JSON-RPC interfaces — solid for testing automation scripts against something that actually behaves like a real vendor OS.
Practical Tips from the Field
Resource Comparison: Containerlab vs GNS3
On the same 8-core, 16 GB RAM machine, running a 5-node OSPF topology:
- GNS3 with Cisco IOS VMs: ~10 GB RAM, 4-8 minutes boot time, one VM per router
- Containerlab with FRRouting: ~400 MB RAM, under 30 seconds, one container per router
- Containerlab with Nokia SR Linux: ~1.2 GB RAM per node, 60-90 seconds, full vendor OS
For most protocol testing — OSPF, BGP, MPLS, routing policies — FRRouting containers give you everything you need at a fraction of the resource cost.
Save and Restore Router Configs
After making manual changes in vtysh, save the config back to the host:
# Save running config from container to host
sudo docker exec clab-bgp-lab-customer vtysh -c "write memory"
sudo docker cp clab-bgp-lab-customer:/etc/frr/frr.conf ./configs/customer/frr.conf
Now your lab config is version-controlled. Push it to Git, share with teammates, recreate the identical lab anywhere.
Integrate Containerlab into CI/CD
The YAML-file-plus-Docker-image model fits naturally into CI pipelines. Validate network config changes before they ever merge:
# .github/workflows/network-test.yml
jobs:
network-lab-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Containerlab
run: bash -c "$(curl -sL https://get.containerlab.dev)"
- name: Deploy lab
run: sudo clab deploy -t tests/bgp-lab.yml
- name: Run connectivity tests
run: |
sleep 30 # Wait for BGP convergence
sudo docker exec clab-bgp-lab-client ping -c 3 192.168.100.1
- name: Destroy lab
if: always()
run: sudo clab destroy -t tests/bgp-lab.yml
Graphing Your Topology
There’s also a built-in topology visualizer:
sudo clab graph -t bgp-lab.yml
This opens a web browser with an interactive topology diagram — useful for documentation and understanding large labs at a glance.
Useful clab Commands to Keep Handy
# List all running labs
sudo clab inspect --all
# Redeploy without destroying (reconfigure)
sudo clab redeploy -t lab01.yml
# Deploy with specific prefix to avoid naming collisions
sudo clab deploy -t lab01.yml --prefix myproject
# Save all node configs at once
sudo clab save -t lab01.yml
If you’re doing serious network engineering or infrastructure automation, Containerlab fluency pays off fast. Spin up, test, break, and rebuild — all in under a minute, no physical lab required, no VM hypervisor tax. Once your topology YAMLs and router configs share a Git repo, the distance between “lab testing” and “production confidence” shrinks to almost nothing.
Start with a two-router FRRouting setup. Get comfortable with the YAML syntax, then graduate to SR Linux or cEOS when you need vendor-specific behavior. An afternoon is enough to get productive.

