Files
infix/dev/container/index.html
T

4209 lines
111 KiB
HTML

<!DOCTYPE html><html lang="en" class="no-js"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Infix Documentation">
<link rel="canonical" href="https://kernelkit.github.io/infix/dev/container/">
<link rel="prev" href="../cli/upgrade/">
<link rel="next" href="../networking/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.7">
<title>Docker Containers - User's Guide</title>
<link rel="stylesheet" href="../assets/stylesheets/main.ec1eaa64.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="stylesheet" href="../extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"><script src="../assets/javascripts/glightbox.min.js"></script><style id="glightbox-style">
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: black; }
.glightbox-clean .gslide-media { -webkit-box-shadow: none; box-shadow: none; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color); }
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color); }
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color); }
</style></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#docker-container-support" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden="">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-header__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
User's Guide
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Docker Containers
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"></path></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="orange" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"></path></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required="">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard="" data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"></path></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix="">
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-nav__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
User's Guide
</label>
<div class="md-nav__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
CLI
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
CLI
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../cli/introduction/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/configure/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/keybindings/" class="md-nav__link">
<span class="md-ellipsis">
Keybindings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/netcalc/" class="md-nav__link">
<span class="md-ellipsis">
Network Calculator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/tcpdump/" class="md-nav__link">
<span class="md-ellipsis">
Network Monitoring
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/quick/" class="md-nav__link">
<span class="md-ellipsis">
Quickstart Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/text-editor/" class="md-nav__link">
<span class="md-ellipsis">
Text Editor
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrading
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Docker Containers
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Docker Containers
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#caution" class="md-nav__link">
<span class="md-ellipsis">
Caution
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#getting-started" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<nav class="md-nav" aria-label="Getting Started">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#example-hello-world" class="md-nav__link">
<span class="md-ellipsis">
Example: Hello World
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#example-web-server" class="md-nav__link">
<span class="md-ellipsis">
Example: Web Server
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#container-images" class="md-nav__link">
<span class="md-ellipsis">
Container Images
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#understanding-image-tags" class="md-nav__link">
<span class="md-ellipsis">
Understanding Image Tags
</span>
</a>
<nav class="md-nav" aria-label="Understanding Image Tags">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Mutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#immutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Immutable Tags
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#upgrading-container-images" class="md-nav__link">
<span class="md-ellipsis">
Upgrading Container Images
</span>
</a>
<nav class="md-nav" aria-label="Upgrading Container Images">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#how-container-lifecycle-works" class="md-nav__link">
<span class="md-ellipsis">
How Container Lifecycle Works
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#method-1-upgrading-immutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Method 1: Upgrading Immutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#method-2-upgrading-mutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Method 2: Upgrading Mutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#embedded-container-images" class="md-nav__link">
<span class="md-ellipsis">
Embedded Container Images
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#capabilities" class="md-nav__link">
<span class="md-ellipsis">
Capabilities
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#resource-limits" class="md-nav__link">
<span class="md-ellipsis">
Resource Limits
</span>
</a>
<nav class="md-nav" aria-label="Resource Limits">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configuring-resource-limits" class="md-nav__link">
<span class="md-ellipsis">
Configuring Resource Limits
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#monitoring-resource-usage" class="md-nav__link">
<span class="md-ellipsis">
Monitoring Resource Usage
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#networking-and-containers" class="md-nav__link">
<span class="md-ellipsis">
Networking and Containers
</span>
</a>
<nav class="md-nav" aria-label="Networking and Containers">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#container-bridge" class="md-nav__link">
<span class="md-ellipsis">
Container Bridge
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#container-host-interface" class="md-nav__link">
<span class="md-ellipsis">
Container Host Interface
</span>
</a>
<nav class="md-nav" aria-label="Container Host Interface">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#routed-setup" class="md-nav__link">
<span class="md-ellipsis">
Routed Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bridged-setup" class="md-nav__link">
<span class="md-ellipsis">
Bridged Setup
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#host-networking" class="md-nav__link">
<span class="md-ellipsis">
Host Networking
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mounts-and-volumes" class="md-nav__link">
<span class="md-ellipsis">
Mounts and Volumes
</span>
</a>
<nav class="md-nav" aria-label="Mounts and Volumes">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#volume-management" class="md-nav__link">
<span class="md-ellipsis">
Volume Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#content-mounts" class="md-nav__link">
<span class="md-ellipsis">
Content Mounts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#example-containers" class="md-nav__link">
<span class="md-ellipsis">
Example Containers
</span>
</a>
<nav class="md-nav" aria-label="Example Containers">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#system-container" class="md-nav__link">
<span class="md-ellipsis">
System Container
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#application-container-nftables" class="md-nav__link">
<span class="md-ellipsis">
Application Container: nftables
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#application-container-ntpd" class="md-nav__link">
<span class="md-ellipsis">
Application Container: ntpd
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#advanced" class="md-nav__link">
<span class="md-ellipsis">
Advanced
</span>
</a>
<nav class="md-nav" aria-label="Advanced">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#running-host-commands-from-container" class="md-nav__link">
<span class="md-ellipsis">
Running Host Commands From Container
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#container-requirements" class="md-nav__link">
<span class="md-ellipsis">
Container Requirements
</span>
</a>
<nav class="md-nav" aria-label="Container Requirements">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#advanced-users" class="md-nav__link">
<span class="md-ellipsis">
Advanced Users
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4">
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Networking
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Networking
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../networking/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../iface/" class="md-nav__link">
<span class="md-ellipsis">
Common Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../bridging/" class="md-nav__link">
<span class="md-ellipsis">
Bridging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../lag/" class="md-nav__link">
<span class="md-ellipsis">
Link Aggregation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ethernet/" class="md-nav__link">
<span class="md-ellipsis">
Ethernet Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vlan/" class="md-nav__link">
<span class="md-ellipsis">
VLAN Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ip/" class="md-nav__link">
<span class="md-ellipsis">
IP Addressing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../routing/" class="md-nav__link">
<span class="md-ellipsis">
Routing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../firewall/" class="md-nav__link">
<span class="md-ellipsis">
Firewall Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../qos/" class="md-nav__link">
<span class="md-ellipsis">
Quality of Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../eth-counters/" class="md-nav__link">
<span class="md-ellipsis">
RMON Counters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tunnels/" class="md-nav__link">
<span class="md-ellipsis">
Tunneling (L2/L3)
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_13">
<label class="md-nav__link" for="__nav_4_13" id="__nav_4_13_label" tabindex="0">
<span class="md-ellipsis">
VPN Tunnels
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_13">
<span class="md-nav__icon md-icon"></span>
VPN Tunnels
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../vpn/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vpn-wireguard/" class="md-nav__link">
<span class="md-ellipsis">
WireGuard
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../wifi/" class="md-nav__link">
<span class="md-ellipsis">
Wireless LAN (WiFi)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Services
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../discovery/" class="md-nav__link">
<span class="md-ellipsis">
Device Discovery
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp/" class="md-nav__link">
<span class="md-ellipsis">
DHCP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ntp/" class="md-nav__link">
<span class="md-ellipsis">
NTP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ptp/" class="md-nav__link">
<span class="md-ellipsis">
PTP (IEEE 1588/802.1AS)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
System
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
System
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../boot/" class="md-nav__link">
<span class="md-ellipsis">
Boot Procedure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../system/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nacm/" class="md-nav__link">
<span class="md-ellipsis">
Access Control (NACM)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../hardware/" class="md-nav__link">
<span class="md-ellipsis">
Hardware Info &amp; Status
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../management/" class="md-nav__link">
<span class="md-ellipsis">
Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../keystore/" class="md-nav__link">
<span class="md-ellipsis">
Keystore
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../syslog/" class="md-nav__link">
<span class="md-ellipsis">
Syslog Support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../support/" class="md-nav__link">
<span class="md-ellipsis">
Support Data
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrade
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7">
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Scripting
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Scripting
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../scripting/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-sysrepocfg/" class="md-nav__link">
<span class="md-ellipsis">
Legacy Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-netconf/" class="md-nav__link">
<span class="md-ellipsis">
NETCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-restconf/" class="md-nav__link">
<span class="md-ellipsis">
RESTCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-prod/" class="md-nav__link">
<span class="md-ellipsis">
Production Testing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8">
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
Developer's Corner
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Developer's Corner
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../branding/" class="md-nav__link">
<span class="md-ellipsis">
Branding &amp; Releases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../developers-guide/" class="md-nav__link">
<span class="md-ellipsis">
Developer's Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../override-package/" class="md-nav__link">
<span class="md-ellipsis">
Developing with Buildroot
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../netboot/" class="md-nav__link">
<span class="md-ellipsis">
Netboot HowTo
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../testing/" class="md-nav__link">
<span class="md-ellipsis">
Regression Testing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../test-arch/" class="md-nav__link">
<span class="md-ellipsis">
Test System Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../virtual/" class="md-nav__link">
<span class="md-ellipsis">
Virtual Environments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vpd/" class="md-nav__link">
<span class="md-ellipsis">
Vital Product Data (VPD)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
Origin &amp; Licensing
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#caution" class="md-nav__link">
<span class="md-ellipsis">
Caution
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#getting-started" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<nav class="md-nav" aria-label="Getting Started">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#example-hello-world" class="md-nav__link">
<span class="md-ellipsis">
Example: Hello World
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#example-web-server" class="md-nav__link">
<span class="md-ellipsis">
Example: Web Server
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#container-images" class="md-nav__link">
<span class="md-ellipsis">
Container Images
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#understanding-image-tags" class="md-nav__link">
<span class="md-ellipsis">
Understanding Image Tags
</span>
</a>
<nav class="md-nav" aria-label="Understanding Image Tags">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Mutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#immutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Immutable Tags
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#upgrading-container-images" class="md-nav__link">
<span class="md-ellipsis">
Upgrading Container Images
</span>
</a>
<nav class="md-nav" aria-label="Upgrading Container Images">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#how-container-lifecycle-works" class="md-nav__link">
<span class="md-ellipsis">
How Container Lifecycle Works
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#method-1-upgrading-immutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Method 1: Upgrading Immutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#method-2-upgrading-mutable-tags" class="md-nav__link">
<span class="md-ellipsis">
Method 2: Upgrading Mutable Tags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#embedded-container-images" class="md-nav__link">
<span class="md-ellipsis">
Embedded Container Images
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#capabilities" class="md-nav__link">
<span class="md-ellipsis">
Capabilities
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#resource-limits" class="md-nav__link">
<span class="md-ellipsis">
Resource Limits
</span>
</a>
<nav class="md-nav" aria-label="Resource Limits">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configuring-resource-limits" class="md-nav__link">
<span class="md-ellipsis">
Configuring Resource Limits
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#monitoring-resource-usage" class="md-nav__link">
<span class="md-ellipsis">
Monitoring Resource Usage
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#networking-and-containers" class="md-nav__link">
<span class="md-ellipsis">
Networking and Containers
</span>
</a>
<nav class="md-nav" aria-label="Networking and Containers">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#container-bridge" class="md-nav__link">
<span class="md-ellipsis">
Container Bridge
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#container-host-interface" class="md-nav__link">
<span class="md-ellipsis">
Container Host Interface
</span>
</a>
<nav class="md-nav" aria-label="Container Host Interface">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#routed-setup" class="md-nav__link">
<span class="md-ellipsis">
Routed Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bridged-setup" class="md-nav__link">
<span class="md-ellipsis">
Bridged Setup
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#host-networking" class="md-nav__link">
<span class="md-ellipsis">
Host Networking
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mounts-and-volumes" class="md-nav__link">
<span class="md-ellipsis">
Mounts and Volumes
</span>
</a>
<nav class="md-nav" aria-label="Mounts and Volumes">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#volume-management" class="md-nav__link">
<span class="md-ellipsis">
Volume Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#content-mounts" class="md-nav__link">
<span class="md-ellipsis">
Content Mounts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#example-containers" class="md-nav__link">
<span class="md-ellipsis">
Example Containers
</span>
</a>
<nav class="md-nav" aria-label="Example Containers">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#system-container" class="md-nav__link">
<span class="md-ellipsis">
System Container
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#application-container-nftables" class="md-nav__link">
<span class="md-ellipsis">
Application Container: nftables
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#application-container-ntpd" class="md-nav__link">
<span class="md-ellipsis">
Application Container: ntpd
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#advanced" class="md-nav__link">
<span class="md-ellipsis">
Advanced
</span>
</a>
<nav class="md-nav" aria-label="Advanced">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#running-host-commands-from-container" class="md-nav__link">
<span class="md-ellipsis">
Running Host Commands From Container
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#container-requirements" class="md-nav__link">
<span class="md-ellipsis">
Container Requirements
</span>
</a>
<nav class="md-nav" aria-label="Container Requirements">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#advanced-users" class="md-nav__link">
<span class="md-ellipsis">
Advanced Users
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="docker-container-support">Docker Container Support<a class="headerlink" href="#docker-container-support" title="Permanent link"></a></h1>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/docker.webp" data-desc-position="bottom"><img align="right" alt="Docker whale" src="../img/docker.webp" width="360"></a></p>
<p>Infix comes with native support for Docker containers using <a href="https://podman.io">podman</a>.
The <a href="https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-containers.yang">YANG model</a> describes the current level of support, complete
enough to run both system and application containers.</p>
<p>Key design features of Infix, like using Linux switchdev, allow users to
assign switch ports directly to containers, not just bridged VETH pairs.
This is a rare and in many cases <em>unique</em> feature of Infix.</p>
<p>All network specific settings are done using the IETF interfaces YANG
model, with augments for containers to ensure smooth integration with
container networking in podman.</p>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>Even though the <code>podman</code> command can be used directly from a shell
prompt, we strongly recommend using the CLI commands instead. They
employ the services of a wrapper <code>container</code> script which handles the
integration of Docker containers in the system.</p>
</div>
<h2 id="caution">Caution<a class="headerlink" href="#caution" title="Permanent link"></a></h2>
<p>A word of warning. Containers can run on your system in privileged
mode, as <code>root</code>, giving them full access to devices on your system.
Even though containers are fenced from the host with Linux namespaces,
resource limited using cgroups, and normally run with capped privileges,
a privileged container is relatively easy to break out of. A trivial
example is given in the <a href="#advanced">Advanced</a> section of this document.</p>
<p>We recommend avoiding privileged containers, if possible (they do have
valid use-cases) and instead use <a href="#capabilities">capabilities</a>.</p>
<p>Remember:</p>
<ul>
<li>If the system is compromised, containers can be used to easily
install malicious software in your system and over the network</li>
<li>Your system is as secure as anything you run in the container</li>
<li>If you run containers, there is no security guarantee of any kind</li>
<li>Running 3rd party container images on your system could open a
security hole/attack vector/surface</li>
<li>An expert with knowledge how to build exploits will be able to
jailbreak/elevate to root even if best practices are followed</li>
</ul>
<p>This being said, a system suspected of being compromised can always be
restored to a safe state with a factory reset. Provided, of course,
that it has secure boot enabled.</p>
<h2 id="getting-started">Getting Started<a class="headerlink" href="#getting-started" title="Permanent link"></a></h2>
<p>In the CLI, containers can be run in one of two ways:</p>
<ol>
<li><code>container run IMAGE [COMMAND]</code>, or</li>
<li>enter <code>configure</code> context, then <code>edit container NAME</code></li>
</ol>
<p>The first is useful mostly for testing, or running single commands in
an image. It is a wrapper for <code>podman run -it --rm ...</code>.</p>
<p>The second creates a read-only container that by default automatically
start at every boot. It basically wraps <code>podman create ...</code>.</p>
<p>When non-volatile storage is needed two complementary options exist:</p>
<ul>
<li><strong>Volumes:</strong> data stored in a volume is persisted until explicitly
removed from the configuration, i.e., across host reboots and
container upgrades</li>
<li><strong><a href="#content-mounts">Content Mounts</a>:</strong> where the content of a file
mounted into the container is kept along with the container
configuration in the device's <code>startup-config</code></li>
</ul>
<p>Podman ensures (using tmpfs) all containers have writable directories
for certain critical file system paths: <code>/dev</code>, <code>/dev/shm</code>, <code>/run</code>,
<code>/tmp</code>, and <code>/var/tmp</code>. Meaning, what you most often need is writable
volumes for <code>/var/lib</code> and <code>/etc</code>, or only file mounts for a few files
in <code>/etc</code>. The <a href="#container-requirements">actual requirements</a> depend on
your container image and application to run.</p>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>When running containers from public registries, double-check that they
support the CPU architecture of your host system. Remember, unlike
virtualization, containers reuse the host's CPU and kernel.</p>
</div>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/docker-hello-world.svg" data-desc-position="bottom"><img align="right" alt="Hello World" src="../img/docker-hello-world.svg" width="200"></a></p>
<h3 id="example-hello-world">Example: Hello World<a class="headerlink" href="#example-hello-world" title="Permanent link"></a></h3>
<p>Classic Hello World:</p>
<pre class="cli"><code>admin@example:/&gt; <b>container run docker://hello-world</b>
Starting docker://hello-world :: use Ctrl-p Ctrl-q to detach
Trying to pull docker.io/library/hello-world:latest...
Getting image source signatures
Copying blob c1ec31eb5944 done
Copying config d2c94e258d done
Writing manifest to image destination
Storing signatures
Hello from Docker!
This message shows that your installation appears to be working correctly.
</code></pre>
<h3 id="example-web-server">Example: Web Server<a class="headerlink" href="#example-web-server" title="Permanent link"></a></h3>
<p>A web server with <a href="https://hub.docker.com/_/nginx">nginx</a>, using standard docker bridge. Podman will
automatically create a VETH pair for us, connecting the container to the
<code>docker0</code> bridge:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit interface docker0</b>
admin@example:/config/interface/docker0/&gt; <b>set container-network</b>
admin@example:/config/interface/docker0/&gt; <b>end</b>
admin@example:/config/&gt; <b>edit container web</b>
admin@example:/config/container/web/&gt; <b>set image docker://nginx:alpine</b>
admin@example:/config/container/web/&gt; <b>set network publish 8080:80</b>
admin@example:/config/container/web/&gt; <b>set network interface docker0</b>
admin@example:/config/container/web/&gt; <b>set volume cache target /var/cache</b>
admin@example:/config/container/web/&gt; <b>leave</b>
admin@example:/&gt; <b>show container</b>
</code></pre>
<p>Exit to the shell and verify the service with curl, or try to attach
to your device's IP address using your browser:</p>
<pre class="cli"><code>admin@example:~$ <b>curl http://localhost:8080</b>
</code></pre>
<p>or connect to port 8080 of your running Infix system with a browser.
See the following sections for how to add more interfaces and manage
your container at runtime.</p>
<h2 id="container-images">Container Images<a class="headerlink" href="#container-images" title="Permanent link"></a></h2>
<p>The underlying <code>podman</code> project supports importing and fetching images in
a variety of ways, the most common ones are also supported by Infix. In
this section we present how to use them and in the next section we show
how to upgrade to a newer base image.</p>
<p>The CLI help shows:</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>help image</b>
<b>NAME</b>
image &lt;string&gt;
<b>DESCRIPTION</b>
Docker image for the container: [transport]name[:tag|@digest]
quay.io/username/myimage -- Pull myimage:latest
docker://busybox -- Pull busybox:latest from Docker Hub
docker://ghcr.io/usr/img -- Pull img:latest from GitHub packages
dir:/media/usb/myimage:1.1 -- Use myimage v1.1 from USB media
docker-archive:/tmp/archive -- Use archive:latest from tarball
oci-archive:/lib/oci/archive -- Use archive:latest from OCI archive
May be in .tar or .tar.gz format
Additionally, the following URIs are also supported for setups
that do not use a HUB or similar. Recommend using 'checksum'!
ftp://addr/path/to/archive -- Downloaded using wget
http://addr/path/to/archive -- Downloaded using curl
https://addr/path/to/archive -- Downloaded using curl
Note: if a remote repository cannot be reached, the creation of the
container will be put on a queue that retries pull every time
there is a route change in the host's system.
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>The built-in help system in the CLI is generated from the YANG model,
so the same information is also available for remote NETCONF users.</p>
</div>
<p>The two most common variants are <code>docker://</code> and <code>oci-archive:/</code>.</p>
<p>The former requires a working Docker registry and the latter operates on
a plain OCI archive. Infix does not come with a built-in registry, so
the <code>docker://</code> option is best used with external services, which in
turn require <a href="../networking/">networking</a> to be up. In a deployment phase the
easiest may be to set up a single interface on your host system with
DHCP client.</p>
<p>The default method is <code>docker://</code>, so when setting the <code>image</code> for your
container, you can omit the <code>docker://</code> prefix. You can also use the
admin-exec command <code>container pull docker://...</code>, and when configuring a
container <code>podman</code> will check first if it has the image before trying to
download anything. (See also the upgrade section, below.)</p>
<p>The <code>oci-archive:/</code> is interesting since many users may not have, or do
not want to, publish their images in a registry. Use the Docker <a href="https://docs.docker.com/build/exporters/oci-docker/">OCI
exporter</a> or any other tool that supports generating <a href="https://github.com/opencontainers/image-spec/blob/main/image-layout.md">OCI Image</a>
format. Infix supports loading both <code>.tar</code> or <code>.tar.gz</code> formats.</p>
<p>Here we show a simple example of fetching an OCI image to the system,
but many others exist, tools like <code>wget</code>, <code>curl</code>, and <code>scp</code> come to
mind.</p>
<p><strong>Shell OCI Example:</strong></p>
<pre class="cli"><code>admin@example:~$ <b>cd /var/tmp/</b>
admin@example:/var/tmp$ <b>sudo wget https://github.com/kernelkit/curiOS/releases/download/edge/curios-oci-amd64.tar.gz</b>
Connecting to github.com (140.82.121.3:443)
wget: note: TLS certificate validation not implemented
Connecting to objects.githubusercontent.com (185.199.109.133:443)
saving to 'curios-oci-amd64.tar.gz'
curios-oci-amd64.tar 100% |*********************************| 7091k 0:00:00 ETA
'curios-oci-amd64.tar.gz' saved
admin@example:/var/tmp$ <b>ll</b>
total 7104
drwxr-xr-x 3 root root 4096 Mar 27 14:22 ./
drwxr-xr-x 14 root root 4096 Mar 27 11:57 ../
-rw-r--r-- 1 root root 7261785 Mar 27 14:22 curios-oci-amd64.tar.gz
drwx------ 6 frr frr 4096 Mar 27 11:57 frr/
</code></pre>
<p>Importing the image into Podman can be done either from the CLI
admin-exec context ...</p>
<pre class="cli"><code>admin@example:/var/tmp$ <b>cli</b>
admin@example:/&gt; <b>container load /var/tmp/curios-oci-amd64.tar.gz name curios:edge</b>
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>The <code>name curios:edge</code> is the tag you give the imported (raw) archive
which you can then reference in your container image configuration:
<code>set image curios:edge</code>.</p>
</div>
<p>... or by giving the container configuration the full path to the OCI
archive, which helps greatly with container upgrades (see below):</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>set image oci-archive:/var/tmp/curios-oci-amd64.tar.gz</b>
</code></pre>
<p><strong>Checksum Example:</strong></p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit container sys</b>
admin@example:/config/container/sys/&gt; <b>set hostname sys</b>
admin@example:/config/container/sys/&gt; <b>set image ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz</b>
admin@example:/config/container/sys/&gt; <b>set checksum</b>
md5 sha256 sha512
admin@example:/config/container/sys/&gt; <b>set checksum sha256 4f01077036527498ed910f1a3e80645ae3eff629d10043cf80ebc6850c99c629</b>
admin@example:/config/container/sys/&gt; <b>leave</b>
admin@example:/&gt; <b>copy running-config startup-config</b>
admin@example:/&gt; <b>show container</b>
<span class="header">NAME STATUS NETWORK MEMORY (KiB) CPU%</span>
sys Up 5 seconds 72/512 0.02
admin@example:/&gt; <b>show log</b>
...
Nov 20 07:24:56 example container[5040]: Fetching ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz
Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz downloaded successfully.
Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz checksum verified OK.
Nov 20 07:24:57 example container[5040]: Cleaning up extracted curios-oci-amd64-v24.05.0
Nov 20 07:24:57 example container[5040]: podman create --name sys --conmon-pidfile=/run/container:sys.pid --read-only --replace --quiet --cgroup-parent=containers --restart=always --systemd=false --tz=local --hostname sys --log-driver k8s-file --log-opt path=/run/containers/sys.fifo --network=none curios-oci-amd64-v24.05.0
Nov 20 07:24:57 example container[3556]: b02e945c43c9bce2c4be88e31d6f63cfdb1a3c8bdd02179376eb059a49ae05e4
</code></pre>
<h2 id="understanding-image-tags">Understanding Image Tags<a class="headerlink" href="#understanding-image-tags" title="Permanent link"></a></h2>
<p>Docker images use tags to identify different versions of the same image.
Understanding the difference between <em>mutable</em> and <em>immutable</em> tags is
important for managing container upgrades effectively.</p>
<h3 id="mutable-tags">Mutable Tags<a class="headerlink" href="#mutable-tags" title="Permanent link"></a></h3>
<p>Tags like <code>:latest</code>, <code>:edge</code>, or <code>:stable</code> are <em>mutable</em> — they point to
different images over time as new versions are published to the registry.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li>Convenient: upgrade without changing configuration</li>
<li>Simple: use the CLI command <code>container upgrade NAME</code> to get the latest version,<br>
there is even a convenient RPC for controlling the remotely</li>
<li>Good for: development, testing, and systems that auto-update</li>
</ul>
<p><strong>Trade-offs:</strong></p>
<ul>
<li>Less reproducible: different systems may run different versions</li>
<li>Less predictable: upgrades happen when you pull, not when you plan</li>
<li>Harder to rollback: previous version may no longer be available</li>
</ul>
<p><strong>Example mutable tags:</strong></p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>docker://nginx:latest # Always points to newest release
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>docker://myapp:edge # Development/bleeding edge version
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>oci-archive:/var/tmp/app.tar # Local archive that may be replaced
</code></pre></div>
<h3 id="immutable-tags">Immutable Tags<a class="headerlink" href="#immutable-tags" title="Permanent link"></a></h3>
<p>Version-specific tags like <code>:v1.0.1</code>, <code>:24.11.0</code>, or digest references
like <code>@sha256:abc123...</code> are <em>immutable</em> — they always reference the
exact same image content.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li>Reproducible: all systems run identical versions</li>
<li>Predictable: upgrades only happen when you change configuration</li>
<li>Auditable: clear history of what ran when</li>
<li>Good for: production, compliance, and controlled deployments</li>
</ul>
<p><strong>Trade-offs:</strong></p>
<ul>
<li>More explicit: must update configuration to upgrade</li>
<li>Requires planning: need to know which version to use</li>
</ul>
<p><strong>Example immutable tags:</strong></p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>docker://nginx:1.25.3 # Specific version number
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>docker://myapp:v2.1.0 # Semantic version tag
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>docker://nginx@sha256:abc123 # Cryptographic digest (most immutable)
</code></pre></div>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p><strong>Best practice for production:</strong> Use specific version tags (<code>:v1.0.1</code>)
rather than mutable tags (<code>:latest</code>). This ensures all your systems run
identical software and upgrades happen only when you decide.</p>
</div>
<h2 id="upgrading-container-images">Upgrading Container Images<a class="headerlink" href="#upgrading-container-images" title="Permanent link"></a></h2>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/shield-checkmark.svg" data-desc-position="bottom"><img align="right" alt="Up-to-date Shield" src="../img/shield-checkmark.svg" width="100"></a></p>
<p>The applications in your container are an active part of the system as a
whole, so make it a routine to keep your container images up-to-date!</p>
<h3 id="how-container-lifecycle-works">How Container Lifecycle Works<a class="headerlink" href="#how-container-lifecycle-works" title="Permanent link"></a></h3>
<p>Infix intelligently manages container lifecycles to provide a smooth
experience while minimizing unnecessary work:</p>
<p><strong>At first setup:</strong> When you configure a container for the first time,
Infix fetches the image (if needed) and creates the container instance.</p>
<p><strong>At boot time:</strong> Infix checks if the container needs to be recreated by
comparing checksums for:</p>
<ul>
<li>The image archive that the container was built from</li>
<li>The container configuration script</li>
</ul>
<p><strong>When configuration changes:</strong> If you modify any container settings
(network, volumes, environment, etc.), the container is automatically
recreated with the new configuration.</p>
<p><strong>When explicitly upgraded:</strong> Using the <code>container upgrade</code> command forces
a fresh pull of the image and recreates the container.</p>
<p>This means that in most cases, <strong>containers persist across reboots</strong> and
are only recreated when actually necessary. Your container's state stored
in volumes is preserved across recreations. Since Infix containers use a
read-only root filesystem, any changes written outside of volumes or the
writable paths provided by Podman (<code>/dev</code>, <code>/dev/shm</code>, <code>/run</code>, <code>/tmp</code>,
<code>/var/tmp</code>) will be lost when the container is recreated.</p>
<h3 id="method-1-upgrading-immutable-tags">Method 1: Upgrading Immutable Tags<a class="headerlink" href="#method-1-upgrading-immutable-tags" title="Permanent link"></a></h3>
<p>When using version-specific tags, you upgrade by explicitly changing the
image reference in your configuration:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit container web</b>
admin@example:/config/container/web/&gt; <b>set image docker://nginx:1.25.3</b>
admin@example:/config/container/web/&gt; <b>leave</b>
</code></pre>
<p><strong>What happens:</strong></p>
<ol>
<li>Podman pulls the new image in the background (if not already present)</li>
<li>Your container is automatically stopped</li>
<li>The container is recreated with the new image</li>
<li>The container is started with your existing volumes intact</li>
</ol>
<p><strong>Example:</strong> Upgrading from one version to another:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit container system</b>
admin@example:/config/container/system/&gt; <b>show image</b>
image ghcr.io/kernelkit/curios:v24.11.0;
admin@example:/config/container/system/&gt; <b>set image ghcr.io/kernelkit/curios:v24.12.0</b>
admin@example:/config/container/system/&gt; <b>leave</b>
admin@example:/&gt; <b>show log</b>
...
Dec 13 14:32:15 example container[1523]: Pulling ghcr.io/kernelkit/curios:v24.12.0...
Dec 13 14:32:18 example container[1523]: Stopping old container instance...
Dec 13 14:32:19 example container[1523]: Creating new container with updated image...
Dec 13 14:32:20 example container[1523]: Container system started successfully
</code></pre>
<h3 id="method-2-upgrading-mutable-tags">Method 2: Upgrading Mutable Tags<a class="headerlink" href="#method-2-upgrading-mutable-tags" title="Permanent link"></a></h3>
<p>For images using mutable tags like <code>:latest</code> or <code>:edge</code>, use the
<code>container upgrade</code> command:</p>
<pre class="cli"><code>admin@example:/&gt; <b>container upgrade NAME</b>
</code></pre>
<p>This command:</p>
<ol>
<li>Stops the running container</li>
<li>Pulls the latest version of the image from the registry</li>
<li>Recreates the container with the new image</li>
<li>Starts the container automatically</li>
</ol>
<p><strong>Example using registry:</strong></p>
<pre class="cli"><code>admin@example:/&gt; <b>container upgrade system</b>
system
Trying to pull ghcr.io/kernelkit/curios:edge...
Getting image source signatures
Copying blob 07bfba95fe93 done
Copying config 0cb6059c0f done
Writing manifest to image destination
Storing signatures
0cb6059c0f4111650ddbc7dbc4880c64ab8180d4bdbb7269c08034defc348f17
system: not running.
59618cc3c84bef341c1f5251a62be1592e459cc990f0b8864bc0f5be70e60719
</code></pre>
<p><strong>Example using local OCI archive:</strong></p>
<p>An OCI archive image can be upgraded in a similar manner. First, get the
new archive onto the system (see Container Images section above), then,
provided the <code>oci-archive:/path/to/archive</code> format is used in your
configuration, call the upgrade command:</p>
<pre class="cli"><code>admin@example:/&gt; <b>container upgrade system</b>
Upgrading container system with local archive: oci-archive:/var/tmp/curios-oci-amd64.tar.gz ...
7ab4a07ee0c6039837419b7afda4da1527a70f0c60c0f0ac21cafee05ba24b52
</code></pre>
<p>OCI archives can also be fetched from ftp/http/https URLs. In that case,
the upgrade works the same way as a registry image — Infix downloads the
new archive and recreates the container.</p>
<h3 id="embedded-container-images">Embedded Container Images<a class="headerlink" href="#embedded-container-images" title="Permanent link"></a></h3>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Containers running from OCI images embedded in the operating system,
e.g., <code>/lib/oci/mycontainer.tar.gz</code>, are automatically kept in sync
with the Infix system image version.</p>
<p><strong>How it works:</strong> When you build a custom Infix image with embedded OCI
archives, those containers will be upgraded whenever you upgrade the
Infix operating system itself. At boot, Infix checks if the embedded
image has changed and automatically recreates the container if needed.</p>
<p><strong>Example:</strong> default builds of Infix include a couple of OCI images
for reference, one is <code>/lib/oci/curios-nftables-v24.11.0.tar.gz</code>, but
there is also a symlink called <code>curios-nftables-latest.tar.gz</code> in the
same directory, which is what the Infix regression tests use in the
image configuration of the container. When the system is upgraded and
the embedded image changes, the test containers are automatically
recreated with the new version.</p>
<p>This approach ensures your embedded containers always match your system
version without any manual intervention.</p>
</div>
<h2 id="capabilities">Capabilities<a class="headerlink" href="#capabilities" title="Permanent link"></a></h2>
<p>An unprivileged container works for almost all use-cases, but there are
occasions where they are too restricted and users start looking for the
<code>privileged</code> flag. Capabilities offers a middle ground.</p>
<p>For example, a system container from which <code>ping</code> does not work:</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>edit capabilities</b>
admin@example:/config/container/system/capabilities/&gt; <b>set add net_raw</b>
admin@example:/config/container/system/capabilities/&gt; <b>end</b>
admin@infix-00-00-00:/config/container/system/&gt; <b>show</b>
...
capabilities {
add net_raw;
}
...
</code></pre>
<p>Infix supports a subset of all <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">capabilities</a> that are relevant for
containers. Please note, that this is an advanced topic that require
time and analysis of your container application to figure out which
capabilities you need.</p>
<h2 id="resource-limits">Resource Limits<a class="headerlink" href="#resource-limits" title="Permanent link"></a></h2>
<p>Containers can be configured with resource limits to control their memory
and CPU usage. This helps prevent containers from consuming excessive system
resources and ensures fair resource allocation across multiple containers.</p>
<h3 id="configuring-resource-limits">Configuring Resource Limits<a class="headerlink" href="#configuring-resource-limits" title="Permanent link"></a></h3>
<p>Resource limits are set per container and include:</p>
<ul>
<li><strong>Memory:</strong> Maximum memory usage in kibibytes (KiB)</li>
<li><strong>CPU:</strong> Maximum CPU usage in millicores (1000 millicores = 1 CPU core)</li>
</ul>
<p>Example configuration limiting a container to 512 MiB of memory and 1.5 CPU cores:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit container web</b>
admin@example:/config/container/web/&gt; <b>edit resource-limit</b>
admin@example:/config/container/web/resource-limit/&gt; <b>set memory 524288</b>
admin@example:/config/container/web/resource-limit/&gt; <b>set cpu 1500</b>
admin@example:/config/container/web/resource-limit/&gt; <b>leave</b>
</code></pre>
<p>Common CPU limit examples:</p>
<ul>
<li><code>500</code> = 0.5 cores (50% of one core)</li>
<li><code>1000</code> = 1.0 cores (one full core)</li>
<li><code>2000</code> = 2.0 cores (two full cores)</li>
</ul>
<h3 id="monitoring-resource-usage">Monitoring Resource Usage<a class="headerlink" href="#monitoring-resource-usage" title="Permanent link"></a></h3>
<p>Runtime resource usage statistics are available in the operational datastore:</p>
<pre class="cli"><code>admin@example:/&gt; <b>show container web</b>
...
</code></pre>
<p>Use <code>show container usage</code> to see resource consumption across all containers,
including memory, CPU, block I/O, network I/O, and process counts.</p>
<h2 id="networking-and-containers">Networking and Containers<a class="headerlink" href="#networking-and-containers" title="Permanent link"></a></h2>
<p>By default, unlike other systems, persistent<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">2</a></sup> containers have no
networking enabled. All network access has to be set up explicitly.
Currently two types of of container networks are supported:</p>
<ul>
<li><code>host</code>: an managed host interface, e.g., one end of a VETH pair,
or even a physical interface</li>
<li><code>bridge</code>: an IP masquerading bridge</li>
</ul>
<p>In the former the interface is delegated to (moved into) the container,
while in the latter a VETH pair is automatically created by Podman and
one end delegated to the container, while the other end is assigned to
the bridge (see the next section).</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>For more information on VETH pairs, see the <a href="../networking/">Networking Guide</a>.</p>
</div>
<h3 id="container-bridge">Container Bridge<a class="headerlink" href="#container-bridge" title="Permanent link"></a></h3>
<p>A container bridge is what most container setups use and users want.</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/cni-bridge-firewall.svg" data-desc-position="bottom"><img alt="IP Masquerading Container Bridge" src="../img/cni-bridge-firewall.svg"></a></p>
<p>The difference from a regular bridge is that the container runtime fully
manages them -- connecting containers with automatically created VETH
pairs (look at the bridge port names) and setting up firewall rules
between the host and other containers, as well as managing port
forwarding. This transparent background management is what makes
container use seem to be so simple.</p>
<p>All interface configuration is done in configure context.</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config&gt; <b>edit interface docker0</b>
admin@example:/config/interface/docker0/&gt; <b>set container-network</b>
admin@example:/config/interface/docker0/&gt; <b>leave</b>
</code></pre>
<p>There is more to this story. When using the CLI, and sticking to common
interface nomenclature, Infix helps you with some of the boring stuff.
E.g., creating a new interface with a name like <code>brN</code> or <code>dockerN</code>
automatically <em>infers</em> the interface types, which you would otherwise
have to set manually:</p>
<pre class="cli"><code>admin@example:/config/interface/docker0/&gt; <b>set type bridge</b>
admin@example:/config/interface/docker0/&gt; <b>set container-network type bridge</b>
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>When configuring the system via an API such as NETCONF or RESTCONF, no
settings are inferred. Instead it is up to the caller to fully define
the desired setup. This makes the CLI very useful for first setup and
then extracting the resulting XML from the shell using the <code>cfg -X</code>
command.</p>
</div>
<p>We have to declare the interface as a container network, ensuring the
interface cannot be used by the system for any other purpose. E.g., a
container <code>host</code> interface is supposed to be used by a container, by
declaring it as such we can guarantee that it would never accidentally
be added as a bridge or lag port. Hence, to move an interface currently
set as a <code>bridge-port</code> it must be removed from the bridge before being
given to a container.</p>
<p>The default subnet for a container <code>bridge</code> is 172.17.0.0/16, the bridge
takes the <code>.1</code> address and hand out the rest of the range to containers
in a round-robin like fashion. A container with this <code>network</code> get an
automatically created VETH pair connection to the bridge and a lot of
other networking parameters (DNS, default route) are set up.</p>
<p>Some of the defaults of a container <code>bridge</code> can be changed, e.g.,
instead of <code>set container-network type bridge</code>, above, do:</p>
<pre class="cli"><code>admin@example:/config/interface/docker0/&gt; <b>edit container-network</b>
admin@example:/config/…/container-network/&gt; <b>set type bridge</b>
admin@example:/config/…/container-network/&gt; <b>edit subnet 192.168.0.0/16</b>
admin@example:/config/…/subnet/192.168.0.0/16/&gt; <b>set gateway 192.168.255.254</b>
admin@example:/config/…/subnet/192.168.0.0/16/&gt; <b>end</b>
admin@example:/config/…/container-network/&gt; <b>edit route 10.0.10.0/24</b>
admin@example:/config/…/route/10.0.10.0/24/&gt; <b>set gateway 192.168.10.254</b>
admin@example:/config/…/route/10.0.10.0/24/&gt; <b>end</b>
admin@example:/config/…/container-network/&gt; <b>end</b>
admin@example:/config/interface/docker0/&gt; <b>leave</b>
</code></pre>
<p>Other network settings, like DNS and domain, use built-in defaults, but
can be overridden from each container. Other common settings per
container is the IP address and name of the network interface inside the
container. The default, after each stop/start cycle, or reboot of the
host, is to name the interfaces <code>eth0</code>, <code>eth1</code>, in the order they are
given in the <code>network</code> list, and to give the container the next address
in a <code>bridge</code>. Below an example of a system container calls <code>set
network interface docker0</code>, here we show how to set options for that
network:</p>
<pre class="cli"><code>admin@example:/config/container/ntpd/&gt; <b>edit network interface docker0</b>
admin@example:/config/…/network/interface/docker0/&gt;
admin@example:/config/…/network/interface/docker0/&gt; <b>set option</b>
&lt;string&gt; Options for masquerading container bridges.
admin@example:/config/…/network/interface/docker0/&gt; <b>help option</b>
NAME
option &lt;string&gt;
DESCRIPTION
Options for masquerading container bridges.
Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6)
mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
interface_name=foo0 -- set interface name inside container
admin@example:/config/…/network/interface/docker0/&gt; <b>set option ip=172.17.0.2</b>
admin@example:/config/…/network/interface/docker0/&gt; <b>set option interface_name=wan</b>
admin@example:/config/…/network/interface/docker0/&gt; <b>leave</b>
</code></pre>
<h3 id="container-host-interface">Container Host Interface<a class="headerlink" href="#container-host-interface" title="Permanent link"></a></h3>
<p>Another common use-case is to move network interfaces into the network
namespace of a container<sup id="fnref:3"><a class="footnote-ref" href="#fn:3">1</a></sup>. This of course works with plain Ethernet
interfaces as well, but here we will use one end of a VETH pair as an
example.</p>
<p>The network <code>option</code> setting is available also for this case, but only
the <code>interface_name=foo0</code> option works. Which is still very useful. To
set:</p>
<ul>
<li>IP address, use IPv4/IPv6 settings in the interface settings</li>
<li>MAC address, to use the <code>custom-phys-address</code> in the interface settings</li>
</ul>
<p>For an example of both, see the next section.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Both ends of a VETH pair may be assigned to containers, connecting two
containers directly without involving the host namespace.</p>
</div>
<h4 id="routed-setup">Routed Setup<a class="headerlink" href="#routed-setup" title="Permanent link"></a></h4>
<p>In this routed setup we reserve 192.168.0.0/24 for the network between
the host and the <code>ntpd</code> container.</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/cni-ntpd-routed.svg" data-desc-position="bottom"><img alt="Basic VETH pair connecting ntpd container." src="../img/cni-ntpd-routed.svg"></a></p>
<p>Configuration is a straight-forward VETH pair setup where we name the
container-end of pair <code>ntpd</code>. This is just a convenience for us when
reading the configuration later. The <em>real action</em> happens on the last
line where we declare the <code>ntpd</code> end as a container network interface:</p>
<pre class="cli"><code>admin@example:/config/&gt; <b>edit interface veth0</b>
admin@example:/config/interface/veth0/&gt; <b>set veth peer ntpd</b>
admin@example:/config/interface/veth0/&gt; <b>set ipv4 address 192.168.0.1 prefix-length 24</b>
admin@example:/config/interface/veth0/&gt; <b>end</b>
admin@example:/config/&gt; <b>edit interface ntpd</b>
admin@example:/config/interface/ntpd/&gt; <b>set ipv4 address 192.168.0.2 prefix-length 24</b>
admin@example:/config/interface/ntpd/&gt; <b>set custom-phys-address static 00:c0:ff:ee:00:01</b>
admin@example:/config/interface/ntpd/&gt; <b>set container-network</b>
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Notice how you can also set a custom MAC address at the same time.</p>
</div>
<p>Adding the interface to the container is the same as before, but since
everything for host interfaces is set up in the interfaces context, we
can take a bit of a shortcut.</p>
<pre class="cli"><code>admin@example:/config/container/ntpd/&gt; <b>set network interface ntpd</b>
admin@example:/config/container/ntpd/&gt; <b>leave</b>
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Use the <code>set network interface ntpd option interface_name=foo0</code> to set
the name of the interface inside the container to <code>foo0</code>.</p>
</div>
<p>The point of the routed case is that port forwarding from the container
in this case is limited to a single interface, not <em>all interfaces</em> as
is the default in the masquerading container bridge setup.</p>
<h4 id="bridged-setup">Bridged Setup<a class="headerlink" href="#bridged-setup" title="Permanent link"></a></h4>
<p>A perhaps more common case is to bridge the other end of the VETH pair
with other physical ports. In this section we show how to add a new
pair to give our container two interfaces:</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/cni-ntpd-bridged.svg" data-desc-position="bottom"><img alt="Bridged setup with ntpd container." src="../img/cni-ntpd-bridged.svg"></a></p>
<p>We start by adding the second VETH pair:</p>
<pre class="cli"><code>admin@example:/config/&gt; <b>edit interface veth1a</b>
admin@example:/config/interface/veth1a/&gt; <b>set veth peer veth1</b>
admin@example:/config/interface/veth1a/&gt; <b>set ipv4 address 192.168.1.2 prefix-length 24</b>
</code></pre>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The LAN bridge (br1) in this example has IP address 192.168.1.1.</p>
</div>
<p>When a container has multiple host interfaces it can often be useful to
have a default route installed. This can be added from the host with a
<code>0.0.0.0/0</code> route on one of the interfaces:</p>
<pre class="cli"><code>admin@example:/config/interface/veth1a/&gt; <b>set container-network route 0.0.0.0/0 gateway 192.168.1.1</b>
admin@example:/config/interface/veth1a/&gt; <b>show</b>
type veth;
container-network {
type host;
route 0.0.0.0/0 {
gateway 192.168.1.1;
}
}
veth {
peer veth1;
}
admin@example:/config/interface/veth1a/&gt; <b>end</b>
admin@example:/config/&gt; <b>set interface veth1 bridge-port bridge br1</b>
</code></pre>
<p>Please note, container network routes require the base interface also
have a static IP address set. Setting only the route, but no address,
means the route is skipped.</p>
<h3 id="host-networking">Host Networking<a class="headerlink" href="#host-networking" title="Permanent link"></a></h3>
<p>The third use-case is host networking, this is where a container share
the network namespace of the host. An example here could be a nftables
or ntpd container -- single applications which add core functionality to
the host operating system.</p>
<p>The host networking setup cannot be combined with any other network.</p>
<p>For an example, <a href="#application-container-nftables">see below</a>.</p>
<h2 id="mounts-and-volumes">Mounts and Volumes<a class="headerlink" href="#mounts-and-volumes" title="Permanent link"></a></h2>
<p>It is possible to mount files, directories, and even files matching a
glob, into a container. This gives precise control over the container's
file system:</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>edit mount leds</b>
admin@example:/config/container/system/mount/leds&gt; <b>set source /sys/class/leds</b>
admin@example:/config/container/system/mount/leds&gt; <b>set target /sys/class/leds</b>
admin@example:/config/container/system/mount/leds&gt; <b>end</b>
admin@example:/config/container/system/&gt;
</code></pre>
<p>Any type of file can be <em>bind mounted</em> into the container, just watch
out for permissions though. In the example above, <code>/sys/class/leds</code> is
not writable from a container unless it runs in <em>privileged</em> mode. For
plain configuration files you get more freedom, and your container can
rely on, e.g., <em>inotify</em> events to trigger reloading its services when
you change the file on the host.</p>
<p>So it depends on the container, and indeed your overall setup, what to
use. An intriguing option is <em>Content Mounts</em>, which when changed also
trigger a container restart.</p>
<p>Other times <em>volumes</em> are a better fit. A volume is an automatically
created read-writable entity that follows the life of your container.</p>
<pre class="cli"><code>admin@example:/config/container/ntpd/&gt; <b>set volume varlib target /var/lib</b>
</code></pre>
<p>Volumes are persistent across both reboots and upgrades of the base
image. They are created by Podman when the container first starts up,
unlike a regular bind mount it synchronizes with the contents of the
underlying container image's path at first use. I.e., "bind-mount, if
empty: then rsync".</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Infix support named volumes (only), and it is not possible to share a
volume between containers. All the tricks possible with volumes may
be added in a later release.</p>
</div>
<h3 id="volume-management">Volume Management<a class="headerlink" href="#volume-management" title="Permanent link"></a></h3>
<p>Volumes are persistent storage that survive container restarts and image
upgrades, making them ideal for application data. However, this also means
they <strong>are not automatically removed</strong> when a container is deleted from the
configuration.</p>
<p>This design choice prevents accidental data loss, especially in scenarios
where:</p>
<ul>
<li>A container is temporarily removed and re-added with the same name</li>
<li>A container is replaced with a different configuration but same name</li>
<li>System upgrades or configuration changes affect container definitions</li>
</ul>
<p>To clean up unused volumes and reclaim disk space, use the admin-exec
command:</p>
<pre class="cli"><code>admin@example:/&gt; <b>container prune</b>
Deleted Images
...
Deleted Volumes
ntpd-varlib
system-data
Total reclaimed space: 45.2MB
</code></pre>
<p>The <code>container prune</code> command safely removes:</p>
<ul>
<li>Unused container images</li>
<li>Volumes not attached to any container (running or stopped)</li>
<li>Other unused container resources</li>
</ul>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>You can monitor container resource usage with the command:</p>
<p></p><pre class="cli"><code>admin@example:/&gt; <b>show container usage</b>
</code></pre><p></p>
<p>This displays disk space used by images, containers, and volumes,
helping you decide when to run the prune command.</p>
<p>To see which volumes exist and which containers use them:</p>
<p></p><pre class="cli"><code>admin@example:/&gt; <b>show container volumes</b>
</code></pre><p></p>
</div>
<h3 id="content-mounts">Content Mounts<a class="headerlink" href="#content-mounts" title="Permanent link"></a></h3>
<p>Content mounts are a special type of file mount where the file contents
is stored with the container configuration. This can be very useful
when deploying similar systems at multiple sites. When the host loads
its <code>startup-config</code> (or even <code>factory-config</code>) a temporary file is
created using the decoded base64 data from the <code>content</code> node.</p>
<pre class="cli"><code>admin@example:/config/container/ntpd/&gt; <b>edit mount ntpd.conf</b>
admin@example:/config/container/ntpd/mount/ntpd.conf&gt; <b>text-editor content</b>
... interactive editor starts up ...
admin@example:/config/container/ntpd/mount/ntpd.conf&gt; <b>set target /etc/ntpd.conf</b>
admin@example:/config/container/ntpd/mount/ntpd.conf&gt; <b>end</b>
admin@example:/config/container/ntpd/&gt;
</code></pre>
<p>The editor is a small <a href="https://github.com/troglobit/mg">Emacs clone called Mg</a>, see the built-in help
text, or press Ctrl-x Ctrl-c to exit and save. When the editor exits
the contents are base64 encoded and stored in the candidate datastore.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Since these files are always recreated when the host is restarted,
changes made by the container are not preserved, or saved back to the
host's startup-config.</p>
</div>
<p>Infix has three different text editors available. For more information,
see <a href="../cli/text-editor/">CLI Text Editor</a>.</p>
<h2 id="example-containers">Example Containers<a class="headerlink" href="#example-containers" title="Permanent link"></a></h2>
<h3 id="system-container">System Container<a class="headerlink" href="#system-container" title="Permanent link"></a></h3>
<p>Let's try out what we've learned by setting up a system container, a
container providing multiple services, using the <code>docker0</code> interface
we created previously:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config&gt; <b>edit container system</b>
admin@example:/config/container/system/&gt; <b>set image ghcr.io/kernelkit/curios:edge</b>
admin@example:/config/container/system/&gt; <b>set network interface docker0</b>
admin@example:/config/container/system/&gt; <b>set publish 222:22</b>
admin@example:/config/container/system/&gt; <b>leave</b>
</code></pre>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Ensure you have a network connection to the registry. If the image
cannot be pulled, creation of the container will be put in a queue and
be retried every time there is a change in the routing table, e.g.,
default route is added, and every 60 seconds.</p>
</div>
<p>Provided the image is downloaded successfully, a new <code>system</code> container
now runs behind the docker0 interface, forwarding container port 22 to
port 222 on all of the host's interfaces. (See <code>help publish</code> in the
container configuration context for the full syntax.)</p>
<p>Available containers can be accessed from admin-exec:</p>
<pre class="cli"><code>admin@example:/&gt; <b>show container</b>
<span class="header">NAME STATUS NETWORK MEMORY (KiB) CPU%</span>
system Up 16 hours docker0 136/512 0.02
</code></pre>
<p>This is a system container, so you can "attach" to it by starting a
shell (or logging in with SSH):</p>
<pre class="cli"><code>admin@example:/&gt; <b>container shell system</b>
root@439af2917b44:/#
</code></pre>
<p>Notice how the hostname inside the container changes. By default the
container ID (hash) is used, but this can be easily changed:</p>
<pre class="cli"><code>root@439af2917b44:/# <b>exit</b>
admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit container system</b>
admin@example:/config/container/system/&gt; <b>set hostname sys101</b>
admin@example:/config/container/system/&gt; <b>leave</b>
admin@example:/&gt; <b>container shell system</b>
root@sys101:/#
</code></pre>
<p>In fact, the container <code>hostname</code> setting supports the same format
specifiers as the host's <code>hostname</code> setting:</p>
<ul>
<li><code>%i</code>: OS ID, from <code>/etc/os-release</code>, from Menuconfig branding</li>
<li><code>%h</code>: Default hostname, from <code>/etc/os-release</code>, from branding</li>
<li><code>%m</code>: NIC specific part of base MAC, e.g., to <code>c0-ff-ee</code></li>
<li><code>%%</code>: Literal %</li>
</ul>
<p>The most useful combination is probably <code>"container-name-%m"</code>, which in
this example give the container hostname <code>container-name-c0-ff-ee</code>.</p>
<h3 id="application-container-nftables">Application Container: nftables<a class="headerlink" href="#application-container-nftables" title="Permanent link"></a></h3>
<p>Infix currently does not have a native firewall configuration, and even
when it does it will never expose the full capabilities of <code>nftables</code>.
For advanced setups, the following is an interesting alternative.</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config&gt; <b>edit container nftables</b>
admin@example:/config/container/nftables/&gt; <b>set image ghcr.io/kernelkit/curios-nftables:edge</b>
admin@example:/config/container/nftables/&gt; <b>set network host</b>
admin@example:/config/container/nftables/&gt; <b>set privileged</b>
admin@example:/config/container/nftables/&gt; <b>edit mount nftables.conf</b>
admin@example:/config/…/mount/nftables.conf/&gt; <b>set target /etc/nftables.conf</b>
admin@example:/config/…/mount/nftables.conf/&gt; <b>text-editor content</b>
... interactive editor starts up where you can paste your rules ...
admin@example:/config/…/mount/nftables.conf/&gt; <b>leave</b>
</code></pre>
<p>Notice how we <code>set network host</code>, so the container can see and act on
all the host's interfaces, and that we also have to run the container
in <em>privileged</em> mode.</p>
<h3 id="application-container-ntpd">Application Container: ntpd<a class="headerlink" href="#application-container-ntpd" title="Permanent link"></a></h3>
<p>The default NTP server/client in Infix is Chrony, a fully working and
capable workhorse for most use-cases. However, it does not support a
feature like multicasting, for that you need ISC ntpd.</p>
<p>As we did with <code>nftables</code>, previously, we can use host networking and
set up a read-only config file that is bind-mounted into the container's
file system and store in the host's <code>startup-config</code>. However, <code>ntpd</code>
also saves clock drift information in <code>/var/lib/ntpd</code>, so we will also
use volumes in this example.</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config&gt; <b>edit container ntpd</b>
admin@example:/config/container/ntpd/&gt; <b>set image ghcr.io/kernelkit/curios-ntpd:edge</b>
admin@example:/config/container/ntpd/&gt; <b>set network interface ntpd</b> # From veth0 above
admin@example:/config/container/ntpd/&gt; <b>edit mount ntp.conf</b>
admin@example:/config/container/ntpd/mount/ntp.conf/&gt; <b>set target /etc/ntp.conf</b>
admin@example:/config/container/ntpd/mount/ntp.conf/&gt; <b>text-editor content</b>
... interactive editor starts up where you can paste your rules ...
admin@example:/config/container/ntpd/mount/ntp.conf/&gt; <b>end</b>
admin@example:/config/container/ntpd/&gt; <b>edit volume varlib</b>
admin@example:/config/container/ntpd/volume/varlib/&gt; <b>set target /var/lib</b>
admin@example:/config/container/ntpd/volume/varlib/&gt; <b>leave</b>
admin@example:/&gt; <b>copy running-config startup-config</b>
</code></pre>
<p>The <code>ntp.conf</code> file is stored in the host's <code>startup-config</code> and any
state data in the container's <code>/var/lib</code> is retained between reboots
and across image upgrades.</p>
<h2 id="advanced">Advanced<a class="headerlink" href="#advanced" title="Permanent link"></a></h2>
<p>This section covers advanced, and sometimes dangerous, topics. Please
read any warnings and always consider the security aspects.</p>
<h3 id="running-host-commands-from-container">Running Host Commands From Container<a class="headerlink" href="#running-host-commands-from-container" title="Permanent link"></a></h3>
<p>SSH login with keys is very handy, both remote scripting friendly <em>and
secure</em>, but it does require a few extra configuration steps. The way
to set it up is covered in part in <a href="../system/#ssh-authorized-key">SSH Authorized Key</a>.</p>
<p>Another <em>insecure</em> approach is to access the host system directly,
bypassing the namespaces that make up the boundary between host and
container.</p>
<div class="admonition warning">
<p class="admonition-title">Caution</p>
<p>Please note, this completely demolishes the isolation barrier between
container and host operating system. It is only suitable in
situations where the container serves more as a unit of distribution
rather than as a separate component of the system. <em>Strongly
recommended</em> to use this only in trusted setups! Consider also
limiting the time frame in which this is active!</p>
</div>
<p>First, enable <em>Privileged</em> mode, this unlocks the door and allows the
container to manage resources on the host system. An example is the
<code>nftables</code> container mentioned previously.</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>set privileged</b>
</code></pre>
<p>Second, mount the host's <code>/proc/1</code> directory to somewhere inside your
container. Here we pick <code>/1</code>:</p>
<pre class="cli"><code>admin@example:/config/container/system/&gt; <b>edit mount host</b>
admin@example:/config/container/system/mount/host/&gt; <b>set source /proc/1</b>
admin@example:/config/container/system/mount/host/&gt; <b>set target /1</b>
admin@example:/config/container/system/mount/host/&gt; <b>leave</b>
</code></pre>
<p>Third, from inside the container, use the host's PID 1 namespaces with
the <code>nsenter</code><sup id="fnref:2"><a class="footnote-ref" href="#fn:2">3</a></sup> command to slide through the container's walls. Here
we show two example calls to <code>hostname</code>, first the container's own name
and then asking what the hostname is on the host:</p>
<pre class="cli"><code>root@sys101:/# <b>hostname</b>
sys101
root@sys101:/# <b>nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname</b>
example
</code></pre>
<p>One use-case for this method is when extending Infix with a management
container that connects to other systems. For some tips on how to
control an Infix system this way, see <a href="../scripting/">Scripting Infix</a>.</p>
<h2 id="container-requirements">Container Requirements<a class="headerlink" href="#container-requirements" title="Permanent link"></a></h2>
<p>In addition to general <a href="https://docs.docker.com/build/building/best-practices/"><em>best practices</em></a> for container images, there
are a few more things to consider when targeting embedded systems:</p>
<ul>
<li>Ensure the image targets the CPU architecture of the target system,<br>
learn more about <a href="https://docs.docker.com/build/building/multi-platform/">Multi-platform Builds</a></li>
<li>Follow <a href="https://docs.docker.com/get-started/docker-concepts/building-images/build-tag-and-publish-an-image/#tagging-images">best practices for naming and tagging</a>, e.g., <code>:latest</code> vs <code>:1.0</code></li>
<li>Follow <a href="https://github.com/opencontainers/image-spec/blob/main/image-layout.md">OCI recommendations and layout</a>,<br>
learn more about <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">OCI and Docker Exporters</a></li>
</ul>
<p>If the <a href="https://www.docker.com/blog/multi-arch-images/">Docker documentation</a> is not enough, there are plenty of
<a href="https://lemariva.com/blog/2018/05/tutorial-docker-on-embedded-systems-raspberry-pi-beagleboard">guides online</a> with examples on how to create your own container
image. For the more advanced, please see the next section.</p>
<h3 id="advanced-users">Advanced Users<a class="headerlink" href="#advanced-users" title="Permanent link"></a></h3>
<p>Most people prefer their system containers small, often based on Alpine
Linux, or similar, with only a few small applications, including their
own, and an SSH server perhaps. For some developers, even this is too
big, so they roll their own from source. This section is for you.</p>
<p>Depending on your needs, here is a checklist:</p>
<ul>
<li>you need something that can forward signals, e.g.,</li>
<li><a href="https://github.com/krallin/tini">tini</a></li>
<li><a href="https://sirikon.me/posts/0009-pid-1-bash-script-docker-container.html">Bash only</a>, or</li>
<li>BusyBox init, a classic most embedded developers know, but read on ...</li>
<li>a system container only need the bare necessities of a system bringup</li>
<li>E.g., BusyBox's init, <a href="https://github.com/kernelkit/curiOS/blob/2e4748f65e356b2c117f586cd9420d7ba66f79d5/board/system/rootfs/etc/inittab">but not everything</a></li>
<li>Some of the networking is set up by Podman and CNI for you, but
you may want to run a DHCP client?</li>
<li>Do <em>not</em> rename interfaces inside the container, use the dedicated
<code>interface_name</code> option in the configuration instead</li>
<li>Remember, Podman provides a <code>tmpfs</code> for all critical system paths:
<code>/dev</code>, <code>/dev/shm</code>, <code>/run</code>, <code>/tmp</code>, and <code>/var/tmp</code>, so you don't
need to clean or set up any of these mount points</li>
</ul>
<p>Examples using <code>tini</code> and BusyBox init are available from the KernelKit
<a href="https://github.com/kernelkit/curiOS/">curiOS project</a>. It is a small Buildroot based container image
builder that generates OCI compatible image tarballs without any tools
from Docker or Podman -- ready-made images exist for testing on both
AMD64 and ARM64 targets, as well as <code>docker pull</code> images and and OCI
tarballs with SHA256 checksums for integrity checking.</p>
<p>Finally, if you build your own version of Infix, and embed OCI tarballs
in the system image, then see the tip at the end of <a href="#embedded-container-images">Upgrading a
Container Image</a> (above).</p>
<div class="footnote">
<hr>
<ol>
<li id="fn:3">
<p>Something which the container bridge network type does behind the
scenes with one end of an automatically created VETH pair.&nbsp;<a class="footnote-backref" href="#fnref:3" title="Jump back to footnote 1 in the text"></a></p>
</li>
<li id="fn:1">
<p>this does not apply to the admin-exec command <code>container run</code>.
This command is intended to be used for testing and evaluating
container images. Such containers are given a private network
behind an IP masquerading bridge.&nbsp;<a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 2 in the text"></a></p>
</li>
<li id="fn:2">
<p>The <code>nsenter</code> program is available from either the util-linux
package in Debian/Ubuntu/Mint, or in BusyBox. Note, however,
it may not be enabled by default in BusyBox.&nbsp;<a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 3 in the text"></a></p>
</li>
</ol>
</div>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright © 2022-2026 The KernelKit Team
</div>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<script id="__config" type="application/json">{"annotate": null, "base": "..", "features": ["toc.follow", "navigation.path", "navigation.instant", "navigation.instant.progress", "navigation.tracking", "navigation.indexes", "search.highlight", "search.share", "content.code.copy", "content.code.annotate", "content.footnote.tooltips"], "search": "../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.d7400e89.min.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(()=>{ lightbox.reload(); });
</script></body></html>