NetPilot
Back to Blog
Tutorial••Updated •7 min

Run the Official MikroTik CHR Image in containerlab

Deploy two RouterOS CHR routers with the mikrotik_chr kind and the official mikrotik/chr image: no vrnetlab build, OSPF from a startup config, and real output from RouterOS 7.24.5.

D
David Kim
DevOps Engineer

The fastest way to run MikroTik RouterOS CHR in containerlab is the mikrotik_chr kind with the official mikrotik/chr image from Docker Hub. There is no disk image to download and no vrnetlab build. You pull the image, write a short topology file, and deploy.

The NetPilot team contributed this kind to containerlab, and it shipped in v0.82.0. Its reference page is in the containerlab documentation, and the merged upstream work is listed on our site. This post walks through a two-router OSPF lab. Every command below ran on containerlab v0.82.0 with RouterOS 7.24.5, and every output is copied from that run.

Ways to run MikroTik CHR

RouteImage stepMulti-node linksRuns onBest for
VirtualBox or VMwareDownload the CHR disk image⚠️ Manual per VMYour PCOne router, first contact
GNS3 or EVE-NGImport the CHR image✅ Drag and dropYour PC or lab serverGraphical labs, offline study
containerlab mikrotik_rosBuild with vrnetlab✅ Topology fileLinux hostExisting vrnetlab pipelines
containerlab mikrotik_chrdocker pull✅ Topology fileLinux hostLabs as code, CI
NetPilotPreloaded on every lab VM✅ AI agent from a promptBrowserNo host to run, mixed-vendor labs

Bottom line: if you have a Linux host, mikrotik_chr is the shortest path to a CHR lab you can keep in Git. If you would rather not run a host, NetPilot preloads the same mikrotik/chr image on every lab VM, and an AI agent builds the lab from a prompt in about 2 minutes.

What you need

  • containerlab v0.82.0 or newer on a Linux host with Docker
  • About 300 MB of memory per CHR node
  • KVM if you have it. Without /dev/kvm the node runs under QEMU emulation and boots several times slower

Step 1: Pull the image

docker pull mikrotik/chr:7.24.5

Tags follow RouterOS versions, plus stable, long-term, testing and development. MikroTik publishes the image for amd64 and arm64.

Step 2: Get the lab

The files are in our public mikrotik-labs repository:

git clone https://github.com/netpilot-labs/mikrotik-labs
cd mikrotik-labs/01-chr-two-routers

The topology is short:

name: chr-two-routers
 
topology:
  kinds:
    mikrotik_chr:
      image: mikrotik/chr:7.24.5
 
  nodes:
    r1:
      kind: mikrotik_chr
      startup-config: r1.rsc
    r2:
      kind: mikrotik_chr
      startup-config: r2.rsc
 
  links:
    - endpoints: ["r1:ether2", "r2:ether2"]

Data ports start at ether2. ether1 is the management interface, and using it in a link is an error.

The startup config is a plain RouterOS script. This is r1.rsc:

/interface bridge add name=loopback0
/ip address add address=10.0.12.1/30 interface=ether2
/ip address add address=10.255.0.1/32 interface=loopback0
/routing ospf instance add name=default router-id=10.255.0.1 version=2
/routing ospf area add name=backbone area-id=0.0.0.0 instance=default
/routing ospf interface-template add area=backbone interfaces=ether2 type=ptp
/routing ospf interface-template add area=backbone interfaces=loopback0 passive

RouterOS has no loopback interface menu, so an empty bridge holds the /32. RouterOS imports the script line by line and stops at the first error. The container log then shows the line and column, and the node does not become ready.

Step 3: Deploy

sudo containerlab deploy -t chr-two-routers.clab.yml

Deploy returns right away, while RouterOS is still booting. Check the health column:

sudo containerlab inspect -t chr-two-routers.clab.yml
╭─────────────────────────┬─────────────────────┬───────────┬───────────────────╮
│           Name          │      Kind/Image     │   State   │   IPv4/6 Address  │
├─────────────────────────┼─────────────────────┼───────────┼───────────────────┤
│ clab-chr-two-routers-r1 │ mikrotik_chr        │ running   │ 172.20.20.2       │
│                         │ mikrotik/chr:7.24.5 │ (healthy) │ 3fff:172:20:20::2 │
├─────────────────────────┼─────────────────────┼───────────┼───────────────────┤
│ clab-chr-two-routers-r2 │ mikrotik_chr        │ running   │ 172.20.20.3       │
│                         │ mikrotik/chr:7.24.5 │ (healthy) │ 3fff:172:20:20::3 │
╰─────────────────────────┴─────────────────────┴───────────┴───────────────────╯

On our host with KVM, each node took about 50 seconds from QEMU start to healthy. The log line that marks the end is chr-launch: RouterOS ready, which you can read with docker logs clab-chr-two-routers-r1.

Step 4: Verify on the RouterOS CLI

Log in with admin and the password admin:

ssh admin@clab-chr-two-routers-r1

LLDP frames cross the link, so the neighbor table already shows the other router:

[admin@r1] > /ip neighbor print
Columns: INTERFACE, ADDRESS4, ADDRESS6, MAC-ADDRESS, IDENTITY
#  INTERFACE  ADDRESS4   ADDRESS6                 MAC-ADDRESS        IDENTITY
0  ether2     10.0.12.2  fe80::5054:ff:fe20:4d01  52:54:00:20:4D:01  r2

OSPF reaches Full:

[admin@r1] > /routing ospf neighbor print
Flags: D - DYNAMIC
0 D instance=default area=backbone interface=ether2 address=10.0.12.2
    router-id=10.255.0.2 state="Full" state-changes=6 adjacency=5s timeout=36s

The routing table shows the far loopback, plus a separate mgmt table:

[admin@r1] > /ip route print
Flags: D - DYNAMIC; A - ACTIVE; c - CONNECT, s - STATIC, o - OSPF
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
#     DST-ADDRESS     GATEWAY           ROUTING-TABLE  DISTANCE
  DAc 10.0.12.0/30    ether2            main                  0
  DAc 10.255.0.1/32   loopback0         main                  0
  DAo 10.255.0.2/32   10.0.12.2%ether2  main                110
  DAc 172.20.20.0/24  ether1            main                  0
;;; clab-mgmt
0  As 0.0.0.0/0       172.20.20.1       mgmt                  1
;;; clab-mgmt
1  As 172.20.20.0/24  ether1            mgmt                  1

That mgmt table is why the lab stays reachable. Management return traffic has its own table, so a default route you add to main, for a dual-WAN test for example, does not cut SSH to the node. Leave the clab-mgmt objects alone, because management depends on them.

A ping between loopbacks proves the route works:

[admin@r1] > /ping 10.255.0.2 count=3 src-address=10.255.0.1
  SEQ HOST                                     SIZE TTL TIME       STATUS
    0 10.255.0.2                                 56  64 321us
    1 10.255.0.2                                 56  64 346us
    2 10.255.0.2                                 56  64 356us
    sent=3 received=3 packet-loss=0% min-rtt=321us avg-rtt=341us
   max-rtt=356us

Other ways in

The node's management address is RouterOS's own ether1 address, so every service answers there with nothing forwarded. The REST API works right away:

curl -u admin:admin http://clab-chr-two-routers-r1/rest/system/resource

Winbox answers on TCP 8291 of the same address. The node's name resolves on the lab host, and the address in the inspect table works from anywhere that can route to it.

Save your work

containerlab save writes each node's /export to ftpboot/config.auto.rsc in its lab directory, without the management objects, so the file works as the startup config of the next deploy. destroy --cleanup deletes the lab directory, so copy the files out first:

sudo containerlab save -t chr-two-routers.clab.yml
sudo cp clab-chr-two-routers/r1/ftpboot/config.auto.rsc r1.rsc
sudo cp clab-chr-two-routers/r2/ftpboot/config.auto.rsc r2.rsc
sudo containerlab destroy -t chr-two-routers.clab.yml --cleanup

The free CHR license

The image runs with the CHR free license, which you can see on the node:

[admin@r1] > /system license print
  system-id: WVunSnChl0J
      level: free

MikroTik documents the free level as running indefinitely, limited to 1 Mbps upload per interface, with all other features available. In our MTCNA lab iperf3 read about 1.3 Mbit/s through a CHR router. Routing, firewall and control plane labs are unaffected. Throughput tests are the one job this license does not fit.

The same lab from a prompt

If you do not want to run a Linux host, describe the lab instead:

"Build two MikroTik CHR routers connected on ether2, with OSPF in area 0 and a loopback on each. Verify the adjacency and ping loopback to loopback."

On NetPilot the agent designs the topology, writes the RouterOS configs, deploys on containerlab in the cloud, and runs the checks. Direct CLI is always available too: open a terminal on any router and run /routing ospf neighbor print yourself. The mikrotik/chr image is preloaded on every lab VM, next to the other network OSes on the supported devices list.

FAQ

How do I run MikroTik CHR in containerlab?

Install containerlab v0.82.0 or newer, set kind: mikrotik_chr and image: mikrotik/chr:7.24.5 on a node in the topology file, and run containerlab deploy. The image is used as published, so no vrnetlab build is needed. Data links start at ether2 because ether1 is the management port.

What is the difference between mikrotik_chr and mikrotik_ros in containerlab?

The mikrotik_chr kind runs the official mikrotik/chr image as MikroTik publishes it. The mikrotik_ros kind runs CHR from an image you build yourself with vrnetlab. Both use the same interface names and startup config format, so a lab moves from one to the other by changing kind and image.

What are the default credentials for a CHR node in containerlab?

The default login is admin with the password admin. If you set custom credentials on the node, the kind creates that user in the full group and disables the factory admin account.

Is the free CHR license enough for a lab?

Yes for routing, firewall and control plane work. MikroTik documents the free license as limited to 1 Mbps upload per interface and says all other CHR features are available without restrictions. In our lab iperf3 read about 1.3 Mbit/s through a CHR router on the free license.

Does the mikrotik_chr kind need KVM?

No. The kind uses KVM when /dev/kvm is available. Without it QEMU runs under TCG emulation, and the node works but boots several times slower.

Next labs

NetPilot is a containerlab contributor and integrator. MikroTik and RouterOS are trademarks of their owner, and NetPilot is not affiliated with MikroTik.

Try NetPilot Free

Build enterprise-grade network labs in seconds with AI assistance

Get Started Free