{"id":16582,"date":"2026-01-18T12:58:14","date_gmt":"2026-01-18T12:58:14","guid":{"rendered":"https:\/\/dmsretail.com\/RetailNews\/building-custom-containers-for-cisco-modeling-labs-cml-a-practical-guide\/"},"modified":"2026-01-18T12:58:14","modified_gmt":"2026-01-18T12:58:14","slug":"building-custom-containers-for-cisco-modeling-labs-cml-a-practical-guide","status":"publish","type":"post","link":"https:\/\/dmsretail.com\/RetailNews\/building-custom-containers-for-cisco-modeling-labs-cml-a-practical-guide\/","title":{"rendered":"Building Custom Containers for Cisco Modeling Labs (CML): A Practical Guide"},"content":{"rendered":"<p> <p><a href=\"https:\/\/dmsretail.com\/online-workshops-list\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-496\" src=\"https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90.png\" alt=\"Retail Online Training\" width=\"729\" height=\"91\" srcset=\"https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90.png 729w, https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90-300x37.png 300w\" sizes=\"auto, (max-width: 729px) 100vw, 729px\" \/><\/a><\/p><br \/>\n<\/p>\n<div>\n<p style=\"text-align: left;\">Container nodes in Cisco Modeling Labs (CML) 2.9 complement virtual machines, offering greater flexibility and efficiency. Engineers benefit from having lightweight, programmable, and rapidly deployable options within their simulation environments. While virtual machines (VMs) dominate with network operating systems, containers add flexibility, enabling tools, traffic injectors, automation, and full applications to run smoothly with your CML topology. Traditional virtual machines are still effective, but custom containers introduce a transformative agility.<\/p>\n<p>Building images that behave predictably and integrate cleanly with simulated networks is much easier with containers. As anyone who has tried to drop a stock Docker image into CML quickly discovers, this isn\u2019t a straightforward process. Typical Docker images lack the necessary CML-compatible metadata, network interface behaviors, and lifecycle properties. Using containers with CML is the missing element.<\/p>\n<p>This blog post provides a practical, engineering-first walkthrough for building containers that are truly CML-ready.<\/p>\n<figure id=\"attachment_483874\" aria-describedby=\"caption-attachment-483874\" style=\"width: 1024px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"lazy lazy-hidden wp-image-483874 size-large\" data-lazy-type=\"image\" src=\"https:\/\/blogs.cisco.com\/gcs\/ciscoblogs\/1\/2026\/01\/Gemini_Generated_Image_x02zm9x02zm9x02z-1024x559.jpg\" alt=\"An illustration of how CML achieves unified integration with cloud computing, network components, and the container platform \" width=\"1024\" height=\"559\"\/><noscript><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-483874 size-large\" src=\"https:\/\/blogs.cisco.com\/gcs\/ciscoblogs\/1\/2026\/01\/Gemini_Generated_Image_x02zm9x02zm9x02z-1024x559.jpg\" alt=\"An illustration of how CML achieves unified integration with cloud computing, network components, and the container platform \" width=\"1024\" height=\"559\"\/><\/noscript><figcaption id=\"caption-attachment-483874\" class=\"wp-caption-text\">CML system (AI-generated)<\/figcaption><\/figure>\n<p><strong>Note about improvements to CML: <\/strong>When containers were introduced, only one image per node definition was allowed. With the CML 2.10 release, this restriction has been lifted. In particular, the following improvements will be added:<\/p>\n<ul>\n<li><strong>Per<\/strong> <strong>image<\/strong> <strong>definition,<\/strong> <strong>Docker<\/strong> <strong>tag<\/strong> <strong>names such as:<\/strong><\/li>\n<\/ul>\n<pre style=\"padding-left: 80px;\"> debian:bookworm, debian:buster and debian:trixie<\/pre>\n<p style=\"padding-left: 80px;\">Are all valid tags for the same \u201cdebian-docker\u201d node definitions\u2014three valid image definitions for one node definition.<\/p>\n<ul>\n<li><strong>Specification of Docker tags as an alternative to image names\u00a0<\/strong>(.tar.gz files) and SHA256 has sums. In this case, CML will try to download the image from a container registry, e.g., Docker Hub, if not otherwise specified.<\/li>\n<li><strong>Improved launch logic\u00a0<\/strong>to avoid \u201cperpetual launches\u201d in case the SHA256 sum from the image definition did not match the actual hash sum in the image.<\/li>\n<\/ul>\n<h2><strong>Why do custom containers in CML matter?<\/strong><\/h2>\n<p>Traditional CML workflows rely on VM-based nodes running IOSv, IOS-XRv, NX-OS, Ubuntu, Alpine, and other operating systems. These are excellent for modeling network operating system behavior, but they\u2019re heavyweight for tasks such as integrating CLI tools, web browsers, ephemeral controllers, containerized apps, microservices, and testing harnesses into your simulations.<\/p>\n<p>Containers start quickly, consume fewer resources, and integrate smoothly with standard NetDevOps CI\/CD workflows. Despite their advantages, integrating standard Docker images into CML isn\u2019t without its challenges, each of which requires a tailored solution for seamless functionality.<\/p>\n<h2><strong>The hidden challenges: why a Docker image isn\u2019t enough<\/strong><\/h2>\n<p>CML doesn\u2019t run containers in the same way a vanilla Docker Engine does. Instead, it wraps containers in a specialized runtime environment that integrates with its simulation engine. This leads to several potential pitfalls:<\/p>\n<ul>\n<li><strong>Entry points and init systems<br \/><\/strong>Many base images assume they\u2019re the <em>only <\/em>process running. In CML, network interfaces, startup scripts, and boot readiness should be provided. Also, CML expects a long-running foreground process. If your container exits immediately, CML will treat the node as \u201cfailed.\u201d<\/li>\n<li><strong>Interface mapping<br \/><\/strong>Containers often use eth0, yet CML attaches interfaces sequentially based on topology (eth0, eth1, eth2\u2026). Your image should handle additional interfaces added at startup, mapping them to specific OS configurations.<\/li>\n<li><strong>Capabilities and users<br \/><\/strong>Some containers drop privileges by default. CML\u2019s bootstrap process may need specific access privileges to configure networking or start daemons.<\/li>\n<li><strong>Filesystem layout<br \/><\/strong>CML uses optional bootstrap assets injected into the container\u2019s filesystem. A standard Docker image won\u2019t have the right directories, binaries, or permissions for this. If needed, CML can \u201cinject\u201d a full suite of command-line binaries (\u201cbusybox\u201d) into a container to provide a proper CLI environment.<\/li>\n<li><strong>Lifecycle expectations<br \/><\/strong>Containers should output log information to the console so that functionality can be observed in CML. For example, a web server should show the access log.<\/li>\n<\/ul>\n<p>Misalign any of these, and you\u2019ll spend hours troubleshooting what appears to be a simple \u201cit works with run\u201d scenario.<\/p>\n<h2><strong>How CML treats containers: A mental model for engineers<\/strong><\/h2>\n<p>CML\u2019s container capabilities revolve around a node-definition YAML file that describes:<\/p>\n<ul>\n<li>The image to load or pull<\/li>\n<li>The bootstrap process<\/li>\n<li>Environment variables<\/li>\n<li>Interfaces and how they bind<\/li>\n<li>Simulation behavior (startup order, CPU\/memory, logging)<\/li>\n<li>UI metadata<\/li>\n<\/ul>\n<p>When a lab launches, CML:<\/p>\n<ul>\n<li>Deploys a container node<\/li>\n<li>Pulls or loads the container image<\/li>\n<li>Applies networking definitions<\/li>\n<li>Injects metadata, IP address, and bootstrap scripts<\/li>\n<li>Monitors node health via logs and runtime state<\/li>\n<\/ul>\n<p>Think of CML as \u201cDocker-with-constraints-plus-network-injection.\u201d Understanding CML\u2019s approach to containers is foundational, but building them requires specifics\u2014here are practical tips to ensure your containers are CML-ready.<\/p>\n<h2><strong>Tips for building a CML-ready container<\/strong><\/h2>\n<p>The container images built for CML 2.10 and forward are created on GitHub. We use a GitHub Action CI workflow to fully automate the build process. You can, in fact, use the same workflow to build your own custom images ready to be deployed in CML. There\u2019s plenty of documentation and examples that you can build off of, provided in the repository* and on the Deep Wiki.**<\/p>\n<p><strong>Important note: <\/strong>CML treats each node in a topology as a single, self-contained service or application. While it might be tempting to directly deploy multi-container applications, often defined using docker-compose , into CML by attempting to split them into individual CML nodes, this approach is generally not recommended and can lead to significant complications.<\/p>\n<h3><strong>1.) Choose the right base<\/strong><\/h3>\n<p>Start from an already existing container definition, like:<\/p>\n<ul>\n<li>nginx (single-purpose network daemon using a vanilla upstream image).<\/li>\n<li>Firefox (graphical user interface, custom build process).<\/li>\n<li>Or a custom CI-built base with your standard automation framework.<\/li>\n<\/ul>\n<p>Avoid using images that rely on SystemD unless you explicitly configure it; SystemD inside containers can be tricky.<\/p>\n<h3><strong>2.) Define a proper entry point<\/strong><\/h3>\n<p>Your container must:<\/p>\n<ul>\n<li>Run a long-lived process.<\/li>\n<li>Not daemonize in the background.<\/li>\n<li>Support predictable logging.<\/li>\n<li>Keep the container \u201calive\u201d for CML.<\/li>\n<\/ul>\n<p>Here\u2019s a simple supervisor script:<\/p>\n<pre>#!bin\/sh&#13;\n&#13;\necho \"Container starting...\"&#13;\n&#13;\ntail\u00a0 -f \/dev\/null<\/pre>\n<p>Not glamorous, but effective. You can replace tail\u00a0 -f \/dev\/null\u00a0 with your service startup chain.<\/p>\n<h3><strong>3.) Prepare for multiple interfaces<\/strong><\/h3>\n<p>CML may attach several interfaces to your topology. CML will run a DHCP process on the first interface, but unless that first interface is L2-adjacent to an external connector in NAT mode, there\u2019s NO guarantee it will acquire one! If it cannot acquire an IP address, it is the lab admin\u2019s responsibility to provide IP address configuration per the day 0 configuration. Typically, ip config \u2026 commands can be used for this purpose.<\/p>\n<h2><strong>Advanced use cases you can unlock<\/strong><\/h2>\n<p>Once you conquer custom containers, CML becomes dramatically more flexible. Some popular use cases among advanced NetDevOps and SRE teams include:<\/p>\n<h3><strong>Synthetic traffic and testing<\/strong><\/h3>\n<h3><strong>Automation engines<\/strong><\/h3>\n<ul>\n<li>Nornir nodes<\/li>\n<li>pyATS\/Genie test harness containers<\/li>\n<li>Ansible automation controllers<\/li>\n<\/ul>\n<h3><strong>Distributed applications<\/strong><\/h3>\n<ul>\n<li>Basic service-mesh experiments<\/li>\n<li>API gateways and proxies<\/li>\n<li>Container-based middleboxes<\/li>\n<\/ul>\n<h3><strong>Security tools<\/strong><\/h3>\n<ul>\n<li>Honeypots<\/li>\n<li>IDS\/IPS components<\/li>\n<li>Packet inspection frameworks<\/li>\n<\/ul>\n<p>Treat CML as a \u201cfull-stack lab,\u201d enhancing its capabilities beyond a mere network simulator.<\/p>\n<h2><strong>Make CML your own lab<\/strong><\/h2>\n<p>Creating custom containers for CML turns the platform from a simulation tool into a complete, programmable test environment. Whether you\u2019re validating automation workflows, modeling distributed systems, prototyping network functions, or simply building lightweight utilities, containerized nodes allow you to adapt CML to your engineering needs\u2014not the other way around.<\/p>\n<p>If you\u2019re ready to extend your CML lab, the best way to start is simple: build a small container, copy and modify an existing node definition, and drop it into a two-node topology. Once you see how smoothly it works, you\u2019ll quickly realize just how far you can push this feature.<\/p>\n<p>Would you like to make your own custom container for CML? Let us know in the comments!<\/p>\n<p>* Github Repository \u2013 Automation for building CML Docker Containers<\/p>\n<p>** DeepWiki \u2013 CML Docker Containers (CML 2.9+)<\/p>\n<p style=\"text-align: center;\" data-ttstextid=\"58\">Sign up for\u00a0Cisco U.\u00a0| Join the\u202f\u00a0Cisco Learning Network\u202ftoday for free.<\/p>\n<blockquote data-ttstextid=\"59\">\n<h2 style=\"text-align: center;\" data-ttstextid=\"60\"><strong>Follow Learn with Cisco\u00a0<\/strong><\/h2>\n<h3 style=\"text-align: center;\" data-ttstextid=\"61\"><strong><a href=\"https:\/\/twitter.com\/LearningatCisco\" target=\"_blank\" rel=\"noopener\">X<\/a>\u202f|\u202fThreads\u00a0|\u00a0Facebook\u202f|\u202fLinkedIn\u202f|\u202fInstagram<\/strong><strong>\u202f|\u202fYouTube<\/strong><\/h3>\n<\/blockquote>\n<p style=\"text-align: center;\" data-ttstextid=\"62\">Use\u202f\u00a0<strong>#CiscoU\u00a0<\/strong>and\u00a0<strong>#CiscoCert<\/strong>\u202fto join the conversation.<\/p>\n<\/p><\/div>\n<p><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><script async defer src=\"https:\/\/platform.instagram.com\/en_US\/embeds.js\"><\/script><br \/>\n<br \/><p><a href=\"https:\/\/dmsretail.com\/online-workshops-list\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-496\" src=\"https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90.png\" alt=\"Retail Online Training\" width=\"729\" height=\"91\" srcset=\"https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90.png 729w, https:\/\/dmsretail.com\/RetailNews\/wp-content\/uploads\/2022\/05\/RETAIL-ONLINE-TRAINING-728-X-90-300x37.png 300w\" sizes=\"auto, (max-width: 729px) 100vw, 729px\" \/><\/a><\/p><br \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Container nodes in Cisco Modeling Labs (CML) 2.9 complement virtual machines, offering greater flexibility and efficiency. Engineers benefit from having lightweight, programmable, and rapidly deployable [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":16583,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-16582","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/posts\/16582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/comments?post=16582"}],"version-history":[{"count":0,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/posts\/16582\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/media\/16583"}],"wp:attachment":[{"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/media?parent=16582"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/categories?post=16582"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dmsretail.com\/RetailNews\/wp-json\/wp\/v2\/tags?post=16582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}