GNS3 2.2.61 Docker Compose 部署指南
用 Docker Compose 部署 GNS3 2.2.61 服务端:顶层项目名 gns3-2.2.61-stack、宿主端口 8133 映射 3080、网络 10.89.63.0/24、数据卷持久化;含官方镜像拉取受限实测、Dynamips 能力集、VPCS 0.8.4 与 uBridge 0.9.19 依赖、KVM 直通缺失与 409/403 排障。
GNS3 2.2.61 Docker Compose 部署指南
目标:用一份
docker-compose.yml把 GNS3 2.2.61 服务端跑起来,端口固定、网络固定、数据可持久化,并能通过浏览器与 REST 接口验证。本文所有命令与回显均来自实测环境(Ubuntu 26.04.1 + Docker 29.9.2 + Compose v5.6.1);GNS3 的组件构成与版本选型见 《GNS3 2.2.61 介绍与选型指南》,裸机安装路线见 《Ubuntu 22.04 安装 GNS3 2.2.61 服务端指南》。
一、环境信息与规划
本章先把宿主机版本、端口与网段钉死。Compose 部署最容易翻车的不是配置文件语法,而是端口冲突、网段冲突、以及容器权限不足导致 Dynamips/uBridge 起不来,所以这三件事在创建容器之前就要查清楚。
1.1 实测环境
| 项目 | 实测值 | 说明 |
|---|---|---|
| 宿主机系统 | Ubuntu 26.04.1 LTS | 内核 7.0.0-38-generic x86_64 |
| Docker Engine | 29.9.2 | 支持 Compose v2 规范 |
| Docker Compose | v5.6.1 | docker compose 子命令 |
| 基础镜像 | ubuntu:22.04 | jammy,Python 3.10,与 GNS3 2.2.x 官方支持一致 |
| 服务端版本 | gns3-server 2.2.61 | 镜像内 venv 安装,PyPI 2026-07-30 发布 |
| 镜像体积 | 519 MB | 本地构建结果 |
| 服务端口 | 8133 → 3080 | 宿主 8133 映射容器 3080 |
| 网络 | 10.89.63.0/24 | 容器固定 IP 10.89.63.10 |
| 演示账号 | root / q1w2e3r4 | 本文示例登录凭据 |
版本自查:
docker version --format '{{.Server.Version}}'
docker compose version --short
cat /etc/os-release | head -2
29.9.2
5.6.1
PRETTY_NAME="Ubuntu 26.04.1 LTS"
NAME="Ubuntu"
1.2 端口规划(8128–8152 段)
GNS3 只用 3080/tcp 提供 HTTP 与 WebSocket;节点 console 走服务端代理,不需要额外映射宿主端口。选端口前先把目标段扫一遍:
ss -ltn | awk '{print $4}' | grep -oE ':(81[2-5][0-9])$' | sort -u
:8121
:8122
:8123
:8129
:8130
:8131
:8132
:8135
:8137
:8150
在 8128–8152 区间内,8133 未被占用,本文选它;部署前用下面这条命令确认一次,返回空即空闲:
ss -ltnp | grep ':8133' || echo "8133 空闲"
8133 空闲
1.3 网络规划(10.89.56–75 槽位)
宿主上已有的 10.89.x 网段(含其他容器栈)必须避开,否则 Docker 会报 Pool overlaps with other one on this address space。先列出现存网段:
docker network ls --format '{{.Name}}' | while read n; do
echo "$n $(docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)"
done
bridge 172.17.0.0/16
dittofeed-v0.24.0-alpha.21-net 10.89.59.0/24
gns3-2.2.61-net 10.89.61.0/24
halo-2271-stack_halo-net 10.89.62.0/24
hoppscotch-v2026-9-stack_hoppscotch-net 10.89.56.0/24
host
none
已占用 56、59、61、62,本文选 10.89.63.0/24,网关 10.89.63.1,服务端固定 IP 10.89.63.10。
1.4 官方镜像现状(实测)
gns3/gns3-server 是 GNS3 官方在 Docker Hub 维护的镜像仓库。本次部署在拉取阶段遇到三类情况,均如实记录:
docker pull gns3/gns3-server:2.2.61
2.2.61: Pulling from gns3/gns3-server
(长时间无进展,最终 context deadline exceeded)
- 直连
registry-1.docker.io超时,docker manifest inspect同样失败; - 通过第三方加速站查询 tag 列表可以看到
["2.2.61","latest"],但取 manifest 返回:
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"gns3/gns3-server","Action":"pull"}]}]}
- 换用其他镜像站分别遇到 "not in the allowlist" 与"免费节点当前繁忙"。
结论:本环境无法确认官方镜像是否已提供 2.2.61 tag,也无法直接从 Docker Hub 拉取。因此本文主路径是"用 ubuntu:22.04 本地构建同版本镜像"(第 2、3 章),保证版本号与裸机安装完全一致;如果你所在环境能正常访问 Docker Hub 或官方镜像已发布 2.2.61,可跳过构建,直接把 compose 里的 build: 段替换为 image: gns3/gns3-server:2.2.61(其余配置不变)。
二、目录结构与配置文件
一个可维护的栈目录应当把"配置、数据、日志"全部落在宿主目录,容器重建不丢数据。下文统一以 /opt/gns3-stack 作为栈目录,所有命令与回显均在该目录结构下实际执行过,路径可按需替换。
mkdir -p /opt/gns3-stack/{config,projects,images,logs}
tree -L 1 /opt/gns3-stack
/opt/gns3-stack
├── config
├── images
├── logs
└── projects
配置文件 /opt/gns3-stack/config/gns3_server.conf:
[Server]
host = 0.0.0.0
port = 3080
config_path = /etc/gns3
projects_path = /var/lib/gns3/projects
images_path = /var/lib/gns3/images
appliances_path = /var/lib/gns3/appliances
symbols_path = /var/lib/gns3/symbols
report_errors = false
local = false
[Qemu]
enable_kvm = false
qemu_path = /usr/bin/qemu-system-x86_64
[Dynamips]
dynamips_path = /usr/bin/dynamips
[VPCS]
vpcs_path = /usr/bin/vpcs
两点必须注意:
port = 3080是容器内端口,宿主端口由 compose 的ports决定,不要把这里改成 8133;enable_kvm = false与本文环境一致(容器未直通/dev/kvm)。若宿主 KVM 可用并已直通,改成true才会带上-enable-kvm启动参数。
各项参数的完整含义与默认值见《GNS3 2.2.61 配置参数详解》。
三、编写 Dockerfile
官方镜像不可用时最稳的做法是自己构建:基础镜像用 ubuntu:22.04,Python 用系统 3.10,gns3-server 用 pip 固定 2.2.61,Dynamips/VPCS/uBridge 三个节点后端一并装好。
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive \
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3 python3-venv python3-pip curl ca-certificates \
qemu-system-x86 qemu-utils dynamips vpcs iproute2 procps \
libpcap0.8 \
&& curl -fsSL -o /tmp/vpcs.deb \
https://ppa.launchpadcontent.net/gns3/ppa/ubuntu/pool/main/v/vpcs/vpcs_0.8.4-1~jammy1_amd64.deb \
&& curl -fsSL -o /tmp/ubridge.deb \
https://ppa.launchpadcontent.net/gns3/ppa/ubuntu/pool/main/u/ubridge/ubridge_0.9.19-1~jammy1_amd64.deb \
&& dpkg -i /tmp/vpcs.deb /tmp/ubridge.deb \
&& rm -f /tmp/vpcs.deb /tmp/ubridge.deb \
&& rm -rf /var/lib/apt/lists/*
RUN python3 -m venv /opt/gns3/venv \
&& /opt/gns3/venv/bin/pip install --upgrade pip \
&& /opt/gns3/venv/bin/pip install gns3-server==2.2.61
RUN mkdir -p /etc/gns3 /var/lib/gns3/projects /var/lib/gns3/images \
/var/lib/gns3/appliances /var/lib/gns3/symbols /var/log/gns3
EXPOSE 3080
ENTRYPOINT ["/opt/gns3/venv/bin/gns3server"]
CMD ["--config", "/etc/gns3/gns3_server.conf", "--log", "/var/log/gns3/gns3_server.log"]
几个设计点,都是实测踩坑后定下来的:
-
VPCS 必须升级到 0.8.x。Ubuntu 22.04 仓库里的 vpcs 是
0.5b2,GNS3 2.2.61 启动 VPCS 节点时会直接返回 409:{"message": "VPCS executable version must be >= 0.6.1 but not a 0.8", "status": 409}所以 Dockerfile 里额外用 GNS3 PPA 的 deb 覆盖安装
1:0.8.4-1~jammy1,构建日志可见:Unpacking vpcs (1:0.8.4-1~jammy1) over (0.5b2-2.2) ... Setting up vpcs (1:0.8.4-1~jammy1) ... -
uBridge 单独安装。它负责节点间链路(虚拟交换机侧),缺失时启动节点会报
uBridge is not available, path doesn't exist...。同样从 PPA 装0.9.19,镜像内验证:docker exec gns3-2.2.61-server ubridge versionuBridge version 0.9.19 running with libpcap version 1.10.1 (with TPACKET_V3) -
pip 使用国内源。直连 pypi.org 下载 14.7 MB 主包时会长时间卡住,构建阶段用
PIP_INDEX_URL指向清华镜像;日志中的成功行为:Successfully installed Jinja2-3.1.6 MarkupSafe-3.0.4 aiofiles-25.1.0 ... gns3-server-2.2.61 ... -
用 venv 而不是系统 pip。Ubuntu 22.04 的 Python 3.10 受 PEP 668 约束,系统级
pip install会报externally-managed-environment;venv 绕开该限制,也让升级/回滚只影响一个目录。
镜像构建并查看结果:
docker compose build
docker images gns3/gns3-server:2.2.61-local
REPOSITORY TAG IMAGE ID CREATED SIZE
gns3/gns3-server 2.2.61-local d2e88f3aa232 1 minute ago 519MB
四、编写 docker-compose.yml
name: gns3-2.2.61-stack
services:
gns3-server:
build:
context: .
dockerfile: Dockerfile
image: gns3/gns3-server:2.2.61-local
container_name: gns3-2.2.61-server
restart: unless-stopped
ports:
- "8133:3080"
volumes:
- ./config/gns3_server.conf:/etc/gns3/gns3_server.conf:ro
- ./projects:/var/lib/gns3/projects
- ./images:/var/lib/gns3/images
- ./logs:/var/log/gns3
environment:
- TZ=Asia/Shanghai
cap_add:
- NET_ADMIN
- NET_RAW
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:3080/v2/version"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
# 若宿主机 /dev/kvm 可用,取消下面两行注释,并在 gns3_server.conf 中设置 enable_kvm = true
# devices:
# - "/dev/kvm:/dev/kvm"
networks:
gns3-net:
ipv4_address: 10.89.63.10
networks:
gns3-net:
name: gns3-2.2.61-stack-net
driver: bridge
ipam:
config:
- subnet: 10.89.63.0/24
gateway: 10.89.63.1
逐项说明:
-
name: gns3-2.2.61-stack:Compose 顶层项目名,决定默认网络名前缀、容器分组名,docker compose ps/logs都以它为准; -
image+build并存:首次用build产出镜像,后续docker compose up -d直接复用本地镜像;如能拉到官方镜像,删掉build改image: gns3/gns3-server:2.2.61即可; -
ports: "8133:3080":宿主 8133 对容器 3080,只暴露一个 HTTP 端口,Web UI、REST、WebSocket 共用; -
三个 volume:
projects、images是业务数据(工程文件与 qcow2 磁盘),必须落在宿主;logs挂载后容器内--log写出的日志可直接在宿主查看; -
cap_add: NET_ADMIN, NET_RAW:这一项不能省。Ubuntu 的/usr/bin/dynamips带文件能力cap_net_admin,cap_net_raw=eip,而 Docker 默认能力集不含这两项,直接执行会失败:docker exec gns3-2.2.61-server dynamips --versionexec /usr/bin/dynamips: operation not permitted加上
cap_add后恢复正常:Cisco Router Simulation Platform (version 0.2.14-amd64/Linux stable) -
healthcheck:用/v2/version判定服务是否真正就绪,比只看容器 Up 更可靠; -
devices: /dev/kvm:仅在宿主 KVM 可用时启用。本文宿主/dev/kvm节点存在但 QEMU 报Could not access KVM kernel module: No such device,所以保持注释、enable_kvm = false,QEMU 节点走 TCG 纯软件模拟。
五、启动与验证
5.1 启动
docker compose up -d
Network gns3-2.2.61-stack-net Creating
Network gns3-2.2.61-stack-net Created
Container gns3-2.2.61-server Creating
Container gns3-2.2.61-server Created
Container gns3-2.2.61-server Starting
Container gns3-2.2.61-server Started
查看状态与健康检查:
docker compose ps
NAME IMAGE STATUS PORTS
gns3-2.2.61-server gns3/gns3-server:2.2.61-local Up 9 seconds (healthy) 0.0.0.0:8133->3080/tcp, [::]:8133->3080/tcp
5.2 接口与 Web UI
curl -s http://127.0.0.1:8133/v2/version
{
"local": false,
"version": "2.2.61"
}
访问根路径会 302 到内置 Web UI:
curl -s -o /dev/null -w 'HTTP %{http_code} redirect=%{redirect_url}\n' http://127.0.0.1:8133/
HTTP 302 redirect=http://127.0.0.1:8133/static/web-ui/bundled
页面标题即 GNS3 Web UI:
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>GNS3 Web UI</title>
<base href="/static/web-ui/">
浏览器打开 http://<宿主IP>:8133/static/web-ui/bundled,用示例账号 root / q1w2e3r4 登录(若在配置里开启了 auth,见 C1 篇)。
5.3 计算节点注册情况
curl -s http://127.0.0.1:8133/v2/computes
[
{
"capabilities": {
"node_types": [
"cloud", "ethernet_hub", "ethernet_switch", "nat", "vpcs",
"virtualbox", "dynamips", "frame_relay_switch", "atm_switch",
"qemu", "vmware", "traceng", "docker", "iou"
],
"platform": "linux",
"version": "2.2.61"
},
"compute_id": "local",
"connected": true,
"cpu_usage_percent": 77.4,
"host": "127.0.0.1",
"last_error": null,
"memory_usage_percent": 56.8,
"name": "c33872afb0de",
"port": 3080,
"protocol": "http",
"user": null
}
]
local compute 已自动连上,说明 controller 与 compute 在同一进程内工作正常。
5.4 创建节点并启动(冒烟测试)
用接口建一个 VPCS 节点,验证节点后端真的能拉起来:
API=http://127.0.0.1:8133/v2
PID=$(curl -s -X POST $API/projects -H 'Content-Type: application/json' \
-d '{"name":"b2-smoke"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["project_id"])')
echo "PID=$PID"
curl -s -X POST $API/projects/$PID/nodes -H 'Content-Type: application/json' \
-d '{"name":"PC1","node_type":"vpcs","compute_id":"local"}' \
| python3 -c 'import sys,json;d=json.load(sys.stdin);print("node",d["name"],d["node_id"],d["node_type"],d["status"])'
PID=801d2acc-c66b-4554-98f4-e8ab62ca94b5
node PC1 fed0a89c-05a6-4d02-a5a8-0afa60a4cbb7 vpcs stopped
启动节点并查看状态:
NID=fed0a89c-05a6-4d02-a5a8-0afa60a4cbb7
curl -s -o /dev/null -w 'start HTTP %{http_code}\n' -X POST $API/projects/$PID/nodes/$NID/start
curl -s $API/projects/$PID/nodes/$NID \
| python3 -c 'import sys,json;d=json.load(sys.stdin);print("status",d["status"],"console",d.get("console"),"console_host",d.get("console_host"))'
start HTTP 200
status started console 5000 console_host 0.0.0.0
清理冒烟工程:
curl -s -X DELETE -o /dev/null -w 'delete HTTP %{http_code}\n' $API/projects/$PID
delete HTTP 204
六、权限、KVM 与常见故障
6.1 KVM 不可用时的表现
容器内默认没有 /dev/kvm:
docker exec gns3-2.2.61-server ls -l /dev/kvm
ls: cannot access '/dev/kvm': No such file or directory
此时 QEMU 节点只能走 TCG:
docker exec gns3-2.2.61-server qemu-system-x86_64 --version
QEMU emulator version 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.31)
要启用 KVM,必须同时满足三件事:宿主内核加载 kvm 模块并可访问 /dev/kvm、compose 里直通该设备、配置中 enable_kvm = true。本文实测宿主 /dev/kvm 存在但 QEMU 打开时报 Could not access KVM kernel module: No such device,因此这条路线在本环境未闭环,只验证了 TCG 路径。
6.2 节点启动返回 409 的两种典型原因
| 现象 | 原样报错 | 处理 |
|---|---|---|
| VPCS 版本过旧 | {"message": "VPCS executable version must be >= 0.6.1 but not a 0.8", "status": 409} | 升级到 PPA 的 1:0.8.4-1~jammy1(本文 Dockerfile 已内置) |
| uBridge 缺失 | "uBridge is not available, path doesn't exist, or you just installed GNS3 and need to restart your user session to refresh user permissions." | 安装 ubridge(本文 Dockerfile 已内置 0.9.19) |
6.3 Dynamips 报 operation not permitted
这是文件能力与容器能力集不匹配,不是二进制损坏:
exec /usr/bin/dynamips: operation not permitted
核对文件能力与容器有效能力:
docker exec gns3-2.2.61-server sh -c 'getcap /usr/bin/dynamips; grep CapEff /proc/self/status'
/usr/bin/dynamips cap_net_admin,cap_net_raw=eip
CapEff: 00000000a80435fb
补 cap_add: [NET_ADMIN, NET_RAW] 后 CapEff 包含对应位,Dynamips 即可执行。
6.4 工程打不开:403 The project is not opened
服务重启后,工程处于关闭状态,直接对节点操作会被拒:
{"message": "The project is not opened", "status": 403}
先打开工程再操作节点:
curl -s -o /dev/null -w 'open HTTP %{http_code}\n' -X POST $API/projects/$PID/open
open HTTP 200
6.5 日志位置
容器内服务日志由启动参数 --log 写入 /var/log/gns3/gns3_server.log,已挂载到宿主 ./logs:
tail -n 5 /opt/gns3-stack/logs/gns3_server.log
2026-10-27 13:44:07 INFO compute.py:436 Connected to compute 'local' WebSocket 'http://127.0.0.1:3080/v2/compute/notifications/ws'
2026-10-27 13:44:13 INFO web_log.py:232 10.89.63.1 ... "GET /v2/version HTTP/1.1" 200 229
2026-10-27 13:44:13 INFO web_log.py:232 10.89.63.1 ... "GET / HTTP/1.1" 302 200
注意:因为日志走了 --log 文件,docker compose logs 基本为空,排障要看挂载出来的文件。
七、数据持久化、升级与备份
-
工程数据:
projects/下每个工程一个目录(内含.gns3工程文件与节点配置),删除容器不影响; -
磁盘镜像:
images/下的 qcow2/镜像文件是节点硬盘,GNS3 首启还会在此安装内置磁盘(empty8G、empty10G 等,约 12 MB),属正常行为; -
升级:改 Dockerfile 里的版本号(如
gns3-server==2.2.61→ 下一补丁版本)后docker compose up -d --build,数据卷不变; -
备份:直接打包宿主目录即可,注意停栈后再打包,避免 qcow2 写入中断:
docker compose stop tar czf gns3-backup-$(date +%F).tar.gz -C /opt gns3-stack/config gns3-stack/projects gns3-stack/images docker compose start -
回滚:镜像按版本打 tag(如
2.2.61-local),保留上一版本镜像,改image字段即可回退。
八、参考与延伸阅读
- GNS3 官方文档:https://docs.gns3.com/
- gns3-server PyPI 发布记录:https://pypi.org/project/gns3-server/
- GNS3 PPA(ubridge / vpcs 新版):https://launchpad.net/~gns3/+archive/ubuntu/ppa
- 站内:《GNS3 2.2.61 介绍与选型指南》
- 站内:《Ubuntu 22.04 安装 GNS3 2.2.61 服务端指南》