$npx -y skills add tikoci/routeros-skills --skill routeros-containerRouterOS /container subsystem for running OCI containers on MikroTik devices. Use when: enabling containers on RouterOS, setting up VETH/bridge networking for containers, managing container lifecycle via CLI or REST API, building OCI images for RouterOS, configuring container env
| 1 | # RouterOS Container Subsystem |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | RouterOS 7.x includes a container subsystem (`/container`) that runs OCI-compatible container images directly on MikroTik hardware. It is NOT Docker — it's MikroTik's own implementation with significant differences. |
| 6 | |
| 7 | **Requirements:** |
| 8 | |
| 9 | - RouterOS 7.x with `container` extra package installed |
| 10 | - Device-mode must be enabled (requires physical access for initial setup) |
| 11 | - Sufficient storage (external USB disk recommended, 100+ MB/s, 10K+ random IOPS) |
| 12 | - ARM, ARM64, or x86 architecture (MIPS not supported for containers) |
| 13 | |
| 14 | ## Device-Mode — Physical Access Required |
| 15 | |
| 16 | Container support is gated behind device-mode, which requires physical confirmation (reset button press or power cycle) to enable: |
| 17 | |
| 18 | ```routeros |
| 19 | # Enable container mode |
| 20 | /system/device-mode/update mode=advanced container=yes |
| 21 | |
| 22 | # After executing: physically confirm within activation-timeout |
| 23 | # - Press reset button, OR |
| 24 | # - Power cycle the device |
| 25 | ``` |
| 26 | |
| 27 | Device-mode is a general RouterOS security feature — not container-specific. It gates many features (scheduler, fetch, sniffer, etc.) across four modes (`home`, `basic`, `advanced`, `rose`) with device-dependent factory defaults. |
| 28 | |
| 29 | For the full feature matrix, modes, update properties, and physical confirmation details: see the [Device-mode reference](../routeros-fundamentals/references/device-mode.md) in the `routeros-fundamentals` skill. |
| 30 | |
| 31 | **Mode script bypass (7.22+):** During netinstall, a mode script (`-sm`) can set device-mode on first boot, automatically triggering a reboot. See the `routeros-netinstall` skill. |
| 32 | |
| 33 | ## Installing the Container Package |
| 34 | |
| 35 | ```routeros |
| 36 | # Check if container package is already installed |
| 37 | /system/package/print where name=container |
| 38 | ``` |
| 39 | |
| 40 | **Method 1: Upload .npk file + apply-changes** (offline) |
| 41 | |
| 42 | ```sh |
| 43 | # Upload via SCP (or Winbox drag-and-drop, or WebFig file upload) |
| 44 | scp container-7.22-arm64.npk admin@router:/ |
| 45 | ``` |
| 46 | |
| 47 | ```routeros |
| 48 | # Apply changes (triggers reboot AND activates — /system/reboot does NOT work!) |
| 49 | /system/package/apply-changes |
| 50 | ``` |
| 51 | |
| 52 | ⚠️ **Critical: `/system/package/apply-changes` was added in RouterOS 7.18.** On 7.18+, always use it — a plain `/system/reboot` discards uploaded packages. On versions <7.18, `/system/reboot` IS the correct (and only) method. (Lab-verified: 7.22.1 uses apply-changes, 7.10 requires reboot. Version check via rosetta command tree.) |
| 53 | |
| 54 | **Method 2: Online package update** (requires internet) |
| 55 | |
| 56 | ```routeros |
| 57 | /system/package/update check-for-updates |
| 58 | /system/package/update install |
| 59 | ``` |
| 60 | |
| 61 | This downloads and installs all available updates including extra packages. To enable a specific package already uploaded but not active, use `/system/package/enable container` then `/system/package/apply-changes`. |
| 62 | |
| 63 | ## Networking Setup |
| 64 | |
| 65 | ### VETH (Virtual Ethernet) |
| 66 | |
| 67 | Containers connect to RouterOS networking via VETH interfaces: |
| 68 | |
| 69 | ```routeros |
| 70 | # Create VETH pair |
| 71 | /interface/veth/add name=veth-myapp address=172.17.0.2/24 gateway=172.17.0.1 |
| 72 | |
| 73 | # The VETH name IS the container's interface name (RouterOS 7.21+) |
| 74 | ``` |
| 75 | |
| 76 | ### Bridge Setup |
| 77 | |
| 78 | ```routeros |
| 79 | # Create a bridge for containers |
| 80 | /interface/bridge/add name=containers |
| 81 | |
| 82 | # Add VETH to the bridge |
| 83 | /interface/bridge/port/add bridge=containers interface=veth-myapp |
| 84 | |
| 85 | # Assign IP to bridge (acts as gateway for containers) |
| 86 | /ip/address/add address=172.17.0.1/24 interface=containers |
| 87 | ``` |
| 88 | |
| 89 | ### NAT / Firewall |
| 90 | |
| 91 | ```routeros |
| 92 | # Masquerade container traffic for internet access |
| 93 | /ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.17.0.0/24 |
| 94 | |
| 95 | # Port forwarding from host to container |
| 96 | /ip/firewall/nat/add chain=dstnat action=dst-nat \ |
| 97 | dst-port=8080 protocol=tcp to-addresses=172.17.0.2 to-ports=80 |
| 98 | |
| 99 | # Allow container bridge in interface list (if firewall restricts) |
| 100 | /interface/list/member/add list=LAN interface=containers |
| 101 | ``` |
| 102 | |
| 103 | ### Layer 2 Networking (Bridge Mode) |
| 104 | |
| 105 | For containers that need to be on the same L2 network as physical interfaces (e.g., netinstall): |
| 106 | |
| 107 | ```routeros |
| 108 | # Add both physical port and VETH to the same bridge |
| 109 | /interface/bridge/port/add bridge=mybridge interface=ether5 |
| 110 | /interface/bridge/port/add bridge=mybridge interface=veth-netinstall |
| 111 | ``` |
| 112 | |
| 113 | This gives the container direct L2 access to devices on ether5. |
| 114 | |
| 115 | ## Environment Variables and Mounts |
| 116 | |
| 117 | There are two ways to attach env vars and mounts to a container (from 7.21+): |
| 118 | |
| 119 | ### Inline (preferred for 7.21+) |
| 120 | |
| 121 | Set `env=` and `mount=` directly on `/container/add` — keeps the container self-contained: |
| 122 | |
| 123 | ```routeros |
| 124 | # Inline env vars and mount (7.21+) |
| 125 | /container/add remote-image=pihole/p |