mcpField
R
routeros-container

routeros-container

github.com/tikoci云与 DevOps8348 次安装5 天前更新
代码仓库

关于 routeros-container

面向 RouterOS 管理者的容器子系统操作指南,涵盖 MikroTik 硬件上的 OCI 容器部署、网络与存储配置及生命周期管理。内容也说明版本差异和本地镜像导入限制。

主要功能

  1. 01启用并安装容器支持
  2. 02配置 VETH、桥接与 NAT
  3. 03设置环境变量和卷挂载
  4. 04从注册表拉取或导入镜像
  5. 05管理容器生命周期与 REST API
  6. 06说明版本属性及镜像限制

适用场景

  1. 01在 MikroTik 设备上部署容器
  2. 02为容器配置网络和端口转发
  3. 03自动化容器部署与管理

MCP 相关

文档提及可使用 rosetta MCP 服务查询 RouterOS 文档和属性;本身不是 MCP 服务。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tikoci/routeros-skills --skill routeros-container

安装后在 Claude Code 中输入/routeros-container确认已加载。

详细介绍

RouterOS 容器子系统

概述

RouterOS 7.x 包含一个容器子系统(/container),可直接在 MikroTik 硬件上运行兼容 OCI 的容器映像。它不是 Docker,而是 MikroTik 自行实现的功能,存在许多显著差异。

要求:

  • 安装了 container 额外软件包的 RouterOS 7.x
  • 必须启用设备模式(初次设置需要现场操作设备)
  • 有足够的存储空间(建议使用外接 USB 磁盘,速度为 100+ MB/s、随机 IOPS 为 10K+)
  • ARM、ARM64 或 x86 架构(容器不支持 MIPS)

设备模式——需要现场操作

容器支持受设备模式控制,需要通过物理确认(按下重置按钮或重启设备)才能启用:

# Enable container mode
/system/device-mode/update mode=advanced container=yes

# After executing: physically confirm within activation-timeout
# - Press reset button, OR
# - Power cycle the device

设备模式是 RouterOS 的通用安全功能,并非容器专属。它会在四种模式(home、basic、advanced、rose)下控制多项功能(调度程序、fetch、嗅探器等),各模式的出厂默认值因设备而异。

完整的功能矩阵、模式、更新属性和物理确认详情,请参阅 routeros-fundamentals 技能中的设备模式参考。

模式脚本绕过(7.22+): 在 netinstall 期间,模式脚本(-sm)可在首次启动时设置设备模式,并自动触发重启。请参阅 routeros-netinstall 技能。

安装容器软件包

# Check if container package is already installed
/system/package/print where name=container

方法 1:上传 .npk 文件 + apply-changes(离线)

# Upload via SCP (or Winbox drag-and-drop, or WebFig file upload)
scp container-7.22-arm64.npk admin@router:/
# Apply changes (triggers reboot AND activates — /system/reboot does NOT work!)
/system/package/apply-changes

⚠️ 重要:/system/package/apply-changes 是在 RouterOS 7.18 中新增的。 在 7.18+ 上,始终使用该命令——直接执行 /system/reboot 会丢弃已上传的软件包。在低于 7.18 的版本中,/system/reboot 是正确且唯一的方法。(经实验室验证:7.22.1 使用 apply-changes,7.10 需要重启。可通过 rosetta 命令树检查版本。)

方法 2:在线更新软件包(需要互联网连接)

/system/package/update check-for-updates
/system/package/update install

此操作会下载并安装所有可用更新,包括额外软件包。若要启用已上传但尚未激活的特定软件包,请使用 /system/package/enable container,然后执行 /system/package/apply-changes。

网络设置

VETH(虚拟以太网)

容器通过 VETH 接口连接到 RouterOS 网络:

# Create VETH pair
/interface/veth/add name=veth-myapp address=172.17.0.2/24 gateway=172.17.0.1

# The VETH name IS the container's interface name (RouterOS 7.21+)
网桥设置
# Create a bridge for containers
/interface/bridge/add name=containers

# Add VETH to the bridge
/interface/bridge/port/add bridge=containers interface=veth-myapp

# Assign IP to bridge (acts as gateway for containers)
/ip/address/add address=172.17.0.1/24 interface=containers
NAT / 防火墙
# Masquerade container traffic for internet access
/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.17.0.0/24

# Port forwarding from host to container
/ip/firewall/nat/add chain=dstnat action=dst-nat \
  dst-port=8080 protocol=tcp to-addresses=172.17.0.2 to-ports=80

# Allow container bridge in interface list (if firewall restricts)
/interface/list/member/add list=LAN interface=containers
二层网络(网桥模式)

对于需要与物理接口处于同一 L2 网络的容器(例如 netinstall):

# Add both physical port and VETH to the same bridge
/interface/bridge/port/add bridge=mybridge interface=ether5
/interface/bridge/port/add bridge=mybridge interface=veth-netinstall

这样容器就可以直接访问 ether5 上的设备。

环境变量和挂载

从 7.21+ 开始,有两种方式可为容器附加环境变量和挂载:

内联方式(7.21+ 优先)

直接在 /container/add 上设置 env= 和 mount=,使容器配置自包含:

# Inline env vars and mount (7.21+)
/container/add remote-image=pihole/pihole:latest interface=veth1 \
  env="TZ=Europe/Riga,WEBPASSWORD=secret" \
  mount="src=disk1/pihole,dst=/etc/pihole" \
  root-dir=disk1/images/pihole logging=yes

/app YAML 底层也是这种实现方式——内联是现代化的配置模式,更便于自动化(无需管理单独关联的对象)。

命名列表(适用于所有版本)

将环境变量和挂载创建为单独对象,然后通过名称引用:

# Create named env list (7.20+ — the 'list=' property groups envs together)
/container/envs/add list=MYAPP key=TZ value="Europe/Riga"
/container/envs/add list=MYAPP key=WEBPASSWORD value="secret"

# Create named mount
/container/mounts/add name=appdata src=disk1/appdata dst=/data

# Reference from container (7.20+ uses 'envlists=', pre-7.20 used 'envlist=')
/container/add file=myimage.tar interface=veth1 \
  envlists=MYAPP mountlists=appdata root-dir=disk1/myapp

最佳实践: 始终将容器卷放在外接磁盘(disk1/)上,切勿放在内部闪存存储中。

属性名称历史

环境变量和挂载引用属性的名称在不同版本间有所变化:

版本环境变量列表分组(/container/envs/add)容器环境变量引用(/container/add)容器挂载引用
7.20 之前仅有 key=、value=(无分组属性)(没有环境变量引用属性)(不可用)
7.20新增 list=新增 envlists=(复数形式)(不可用)
7.21+list=envlists= + 内联 env=mountlists= + 内联 mount=

版本说明: 7.20+ 的属性名称已通过 /console/inspect 命令树数据确认。在 7.20 之前,/container/envs/add 只有 key 和 value,没有分组机制;/container/add 没有环境变量引用属性。内联 env= 和 mount= 是在 7.21 中新增的。

容器镜像格式

RouterOS 接受以下格式的容器镜像:

选项 A:从注册表拉取
/container/config/set registry-url=https://registry-1.docker.io tmpdir=disk1/pull
/container/add remote-image=library/alpine:latest interface=veth-myapp
选项 B:导入本地 Tar 文件

将 Docker v1 tar 上传到路由器,然后:

/container/add file=myimage.tar interface=veth-myapp
本地导入的 OCI 镜像要求

RouterOS 的容器加载器对本地 tar 文件有特定要求:

  1. 仅限单层 — 不支持多层镜像
  2. 不支持 gzip 压缩 — 层必须是未压缩的 tar
  3. Docker v1 清单格式 — manifest.json + config.json + layer.tar
myimage.tar
├── manifest.json    # [{"Config":"config.json","RepoTags":["name:tag"],"Layers":["layer.tar"]}]
├── config.json      # {"architecture":"arm64","os":"linux","config":{...},"rootfs":{...}}
└── layer.tar        # Uncompressed tar of the full filesystem

这些限制是它与标准 OCI 镜像的主要区别——大多数来自公共注册表的基础镜像在通过注册表拉取时已满足要求 1 和 2;本地构建的 tar 必须满足全部三项要求。

容器生命周期

CLI
# Create container (7.21+ inline syntax)
/container/add file=myimage.tar interface=veth-myapp \
  env="MY_VAR=hello" mount="src=disk1/appdata,dst=/data" \
  root-dir=disk1/myapp logging=yes

# Start
/container/start [find tag~"myapp"]

# Stop
/container/stop [find tag~"myapp"]

# View status
/container/print

# View logs (if logging=yes)
/log/print where topics~"container"

# Remove (must be fully stopped first)
/container/remove [find tag~"myapp"]
REST API
const base = "http://192.168.1.1/rest";
const auth = { headers: { Authorization: `Basic ${btoa("admin:")}` } };

// List containers
const containers = await fetch(`${base}/container`, auth).then(r => r.json());

// Start container by ID
await fetch(`${base}/container/start`, {
  method: "POST", ...auth,
  headers: { ...auth.headers, "Content-Type": "application/json" },
  body: JSON.stringify({ ".id": "*1" }),
});

// Check status — .running field is "true"/"false" (strings!)
const status = await fetch(`${base}/container/*1`, auth).then(r => r.json());
if (status.running === "true") { /* container is running */ }

// Stop container
await fetch(`${base}/container/stop`, {
  method: "POST", ...auth,
  body: JSON.stringify({ ".id": "*1" }),
});

// Delete — must be fully stopped. Poll .running and retry.
async function deleteContainer(id) {
  for (let i = 0; i < 5; i++) {
    const c = await fetch(`${base}/container/${id}`, auth).then(r => r.json());
    if (c.running === "false") {
      await fetch(`${base}/container/${id}`, { method: "DELETE", ...auth });
      return;
    }
    await new Promise(r => setTimeout(r, 3000));
  }
  throw new Error("Container did not stop in time");
}
容器 REST API 注意事项
  • .running 字段是状态指示器——其值是字符串 "true" / "false",而不是布尔值
  • 不存在 .stopped 字段——只需检查 .running
  • 停止过程中删除 = HTTP 400——必须轮询 .running,直到值为 "false" 后再执行 DELETE
  • 本地 tar 使用 file=,从注册表拉取使用 remote-image=
  • 容器的 envlists=(复数,7.20+)引用环境列表名称——注意这里是复数。7.20 之前使用 envlist=(单数)。请参阅上文的环境变量/挂载版本历史。

容器属性(7.22 起)

/container/add 的部分属性。这并非完整列表——要查看特定版本的完整列表,请使用 rosetta MCP 工具(/container/add 处的 routeros_command_tree)。

属性描述
interfaceVETH 接口
env内联环境变量(7.21+)。以逗号分隔的 KEY=value 对
envlists命名环境列表引用(7.20+)。请参阅上文的环境变量/挂载部分
mount内联卷挂载(7.21+)。src=host/path,dst=/container/path
mountlists命名挂载列表引用(7.21+)。请参阅上文的环境变量/挂载部分
root-dir容器文件系统的存储位置
file容器 tar 文件(本地导入)
remote-image容器镜像名称(从注册表拉取)
cmd覆盖容器 CMD
entrypoint覆盖容器 ENTRYPOINT
hostname容器主机名
dns容器的 DNS 服务器
logging是否将容器 stdout/stderr 写入 RouterOS 日志(yes/no)
start-on-boot设备启动时自动启动容器(yes/no)
workdir覆盖工作目录
name容器名称(用于 [find where name=...])
devices直通物理设备(7.20+)
cpu-listCPU 核心亲和性
memory-highRAM 使用量上限,单位为字节

架构映射

从注册表拉取或构建镜像时,请将 RouterOS 架构映射到 Docker 平台:

RouterOS architecture-nameDocker 平台
armlinux/arm/v7
arm64linux/arm64
x86linux/amd64

查询路由器的架构:

const resource = await fetch(`${base}/system/resource`, auth).then(r => r.json());
const arch = resource["architecture-name"]; // "arm64", "arm", "x86"

/app 系统(7.21+/7.22+)

RouterOS 7.21 引入了 /app 路径(内置应用列表)。完整的 YAML 应用创建(/app/add)于 7.22 加入。完整的 YAML 规范请参阅 routeros-app-yaml 技能。

/app 与手动容器设置

如果需要完整控制 VETH/bridge/L2(例如 netinstall、DHCP 中继或其他原始 L2 工作流),请使用手动 /container 设置。对于符合 RouterOS 应用联网和端口转发惯例的标准多容器应用,请使用 /app YAML。

其他资源

相关技能:

  • 有关 netinstall 和设备模式自动化:请参阅 routeros-netinstall 技能
  • 有关 /app YAML 格式:请参阅 routeros-app-yaml 技能
  • 有关 RouterOS 基础知识(CLI、REST、脚本):请参阅 routeros-fundamentals 技能

MCP 工具:

  • 有关 RouterOS 文档和属性查询:请使用 rosetta MCP 服务工具(routeros_search、routeros_get_page、routeros_search_properties)

外部文档:

评论

支持 Markdown