To run Arista cEOS in containerlab, import the cEOS-lab archive with docker import and use the arista_ceos kind. That part takes minutes and the containerlab docs cover it well. This tutorial covers it too, then spends its time on what the docs leave you to find: five traps that stop a first lab, each one reproduced on a real run.
Everything below ran on containerlab v0.82.0 and v0.77.0 on Ubuntu 24.04, on cEOS-lab 4.36.1F. containerlab is an independent open source project, and NetPilot is a contributor and integrator. The labs are public at netpilot-labs/arista-labs. The image is Arista's, so it is not in that repository.
NetPilot runs the same image on a cloud lab VM. You upload your cEOS archive under Images, and the fixes in this post become the agent's job. The rest of this post is for running it on your own host.
Where to run cEOS
| Route | Runs on | Image | Best for |
|---|---|---|---|
| containerlab on your host | Your Linux machine | Yours, from arista.com | Full control, your own topologies |
| Arista Community Labs | Arista's hosted labs, in the browser | Provided through your Arista account | Ready-made Arista exercises |
| NetPilot | A hosted lab VM | Yours, uploaded once | A multi-vendor topology built from a prompt |
If you want a ready-made Arista exercise, start with Arista Community Labs. The only local software they need is a web browser, and their quickstart asks for an Arista account on a corporate email domain. If you want your own topology, or Arista beside other vendors, keep reading.
Step 1: Get the image
Register at arista.com, open Software Downloads, and download the cEOS64-lab archive for your release. Import it with docker import, because the archive is a filesystem and not a saved image. docker load is the wrong command here.
docker import cEOS64-lab-4.36.1F.tar.xz ceos:4.36.1F
docker images ceos --format '{{.Repository}}:{{.Tag}} {{.Size}}'ceos:4.36.1F 2.64GBStep 2: Deploy two switches
You need Docker and containerlab on a Linux host, and no KVM, because cEOS is a plain container. This is lab 01: two switches on eBGP with a Linux host behind each one.
name: arista-two
topology:
kinds:
arista_ceos:
image: ceos:4.36.1F
linux:
image: ghcr.io/srl-labs/network-multitool:latest
nodes:
sw1:
kind: arista_ceos
startup-config: configs/sw1.cfg
sw2:
kind: arista_ceos
startup-config: configs/sw2.cfg
h1:
kind: linux
exec:
- ip link set eth1 mtu 1500
- ip addr add 10.1.1.10/24 dev eth1
- ip route replace 10.0.0.0/8 via 10.1.1.1
h2:
kind: linux
exec:
- ip link set eth1 mtu 1500
- ip addr add 10.2.2.10/24 dev eth1
- ip route replace 10.0.0.0/8 via 10.2.2.1
links:
- endpoints: ["sw1:eth1", "sw2:eth1"]
- endpoints: ["sw1:eth2", "h1:eth1"]
- endpoints: ["sw2:eth2", "h2:eth1"]The sw1 startup config:
hostname sw1
!
username admin privilege 15 role network-admin secret admin
!
ip routing
!
interface Ethernet1
no switchport
ip address 10.0.12.0/31
!
interface Ethernet2
no switchport
ip address 10.1.1.1/24
!
interface Loopback0
ip address 10.255.0.1/32
!
router bgp 65001
router-id 10.255.0.1
neighbor 10.0.12.1 remote-as 65002
network 10.1.1.0/24
network 10.255.0.1/32
!
management api http-commands
no shutdown
!
endDeploy it:
git clone https://github.com/netpilot-labs/arista-labs
cd arista-labs/01-two-switches
sudo containerlab deploy -t two-switches.clab.ymlDeploy returned in 29 seconds, and BGP was established at 36 seconds from the start. A topology link named eth1 is Ethernet1 on the switch. Open the CLI with docker exec:
docker exec -it clab-arista-two-sw1 Clisw1#show ip bgp summary
BGP summary information for VRF default
Router identifier 10.255.0.1, local AS number 65001
Neighbor Status Codes: m - Under maintenance
Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc PfxAdv
10.0.12.1 4 65002 5 5 0 0 00:00:09 Estab 2 2 2And end to end through both switches:
$ docker exec clab-arista-two-h1 ping -c3 10.2.2.10
3 packets transmitted, 3 received, 0% packet loss, time 2004msThe five traps
1. A custom startup-config removes the admin user
With no startup-config, containerlab gives the node a default config with an admin user, eAPI, gNMI and NETCONF. Point it at your own file and that default is gone. Our first version of this lab had no username line. docker exec worked, and SSH did not:
admin@clab-arista-two-sw1: Permission denied (publickey,keyboard-interactive).show management api http-commands said Enabled: No as well. That is why the config above carries the username line and the management api http-commands block. Naming the file .partial does not help, the admin user was missing that way too.
2. Without no switchport, the IP does nothing
Leave out no switchport and EOS gives no error at boot. The ip address line stays in the running config, and the port stays in VLAN 1:
a#show running-config interfaces Ethernet1
interface Ethernet1
ip address 10.0.1.0/31
a#show interfaces status
Port Name Status Vlan Duplex Speed Type Flags Encapsulation
Et1 connected 1 full 1G EbraTestPhyPort
Et2 connected routed full 1G EbraTestPhyPortCheck the Vlan column for routed before you debug BGP. In the same run, no ip routing is the default on a node with no startup config, so add ip routing too.
3. Ping works and TCP stalls
containerlab gives Linux nodes an MTU of 9500 on data links. A routed port on cEOS has an IP MTU of 1500. Small pings pass, so the lab looks healthy, and then TCP sends segments the switch cannot route. On the first version of this lab, with the default MTU:
$ docker exec clab-arista-two-h1 iperf3 -c 10.2.2.10 -t 5 -f m
[ 5] 0.00-5.00 sec 341 KBytes 0.56 Mbits/sec 11 sender
[ 5] 0.00-5.00 sec 0.00 Bytes 0.00 Mbits/sec receiverWith ip link set eth1 mtu 1500 on both hosts, as in the topology above:
[ 5] 0.00-5.00 sec 33.8 MBytes 56.6 Mbits/sec 0 sender
[ 5] 0.00-5.25 sec 32.8 MBytes 52.5 Mbits/sec receiverForwarding is in software, so read that number as this lab's rate and never as a switch's rate.
4. docker restart hangs the node
Restarting a cEOS container loses its veth links, and the node waits for them before it boots. The CLI stops answering, and the logs show why:
$ docker logs --tail 1 clab-arista-two-sw1
Connected 0 interfaces out of 2 (waited 235s)Use containerlab instead. containerlab destroy without --cleanup, then deploy, keeps the node's flash directory. A change we saved with write memory and containerlab save was still there after that cycle, and BGP was up 3 seconds after the deploy returned.
5. A directory Docker cannot see boots the switch empty
Our first deploy ran from a /tmp that was private to one systemd service. containerlab wrote the configs there, and Docker mounted the real /tmp, which held none of them. The deploy still reported success. The switches then sat in Zero Touch Provisioning with no config:
localhost#show ip bgp summary
% BGP inactive at line 1
localhost#show zerotouch
ZeroTouch Mode: Active
Script Exec Timeout: 900The device calls itself localhost, and the login banner says No startup-config was found. If you see that, the node did not get your file. Run the lab from a normal directory.
Memory and scale
Each cEOS node used 1.15 to 1.45 GiB in docker stats shortly after boot, so plan for about 1.5 GB a node. The containerlab docs say the image supports up to 50 nodes per host from 4.32.0F, with extra inotify settings beyond that.
The same lab on NetPilot
NetPilot uses this image and this kind on a hosted lab VM, and it needs a Large VM for cEOS. You download the archive from Arista and upload it under Images in the app. NetPilot imports it on your VM, and it is ready for the agent.
Ask the agent:
"Build two Arista cEOS switches on eBGP, each with a Linux host, and prove the hosts can reach each other."
The agent writes the topology and the startup configs, deploys them, and checks the result on the devices. That prompt is an example. We ran the tools underneath on a lab VM: set_topology, set_configs, a containerlab deploy, then execute_commands, and the two switches reached Estab. Direct CLI is always there too. Every switch has a console, so you can run the commands in this post by hand.
The agent's links are named eth1_1, so the ports read Ethernet1/1 on the switch. The config is the same.
See a bigger fabric
Episode 2 of our lab series builds a two-spine, four-leaf EVPN-VXLAN fabric on cEOS:
FAQ
How do I run Arista cEOS in containerlab?
Download the cEOS64-lab archive from arista.com, import it with docker import, and use the arista_ceos kind in a topology file. Deploy took about 30 seconds in our runs and BGP came up about 7 seconds after that.
Where do I download Arista cEOS?
From Software Downloads on arista.com. You need to register an account first. The image is not on a public registry, and the archive is imported with docker import rather than docker load.
What is the difference between cEOS and vEOS?
cEOS-lab is EOS as a container, and it shares the host kernel. vEOS-lab is EOS as a virtual machine. In containerlab, cEOS uses the arista_ceos kind and starts as a plain container, and the arista_veos kind runs a QEMU VM built with vrnetlab, which the containerlab docs give about 4 minutes to boot. Pick cEOS unless you need something only the VM packaging gives you.
How much memory does an Arista cEOS node need?
We measured 1.15 to 1.45 GiB per node on cEOS-lab 4.36.1F, read with docker stats shortly after boot. Plan for about 1.5 GB per node.
Why can't I SSH to my cEOS node in containerlab?
A custom startup-config replaces the default config, and the admin user goes with it. docker exec still works and SSH answers Permission denied. Add a username line to the file.
Can I run Arista cEOS without installing Docker?
Yes. Arista Community Labs run in the browser, and NetPilot runs cEOS on a hosted lab VM from an image you upload. Both need you to have an Arista account for the image.
Next steps
- Arista MLAG lab: an MLAG pair with VARP, and three failover timers measured
- containerlab in the cloud: the engine, hosted for you
- EVPN-VXLAN data center guide: the fabric the video builds
- Supported devices: every network OS you can run on NetPilot
- Open source contributions: what the NetPilot team sends upstream