
Moonbeam
用 Docker 启动 Moonbeam 本地开发节点并连接预置账户
面向在 Moonbeam 上构建 dApp 的开发者,讲清如何用 Docker 拉起一个无需中继链的本地开发节点,包括即时出块、定时出块与手动出块三种封块模式,预置测试账户的地址与私钥,链 ID 对照,以及从源码构建节点、运行测试和懒加载节点的做法。
Moonbeam 是一条构建在 Polkadot-SDK 之上的、兼容以太坊的智能合约平行链。对在它上面写 dApp 的开发者来说,最常遇到的第一道门槛不是合约本身,而是「本地没有一条能随时出块、随时重置、账户里还有余额的链」。本文要解决的就是这件事:用 Docker 启动一个 Moonbeam 本地开发节点,让它按你需要的节奏出块,并用预置账户直接开始部署与调试。如果你只是想先看看这个工具在站内的位置,可以从 Moonbeam 这一条目入手,再回到本文按步骤操作。
本文适合两类读者:一类是准备在 Moonbeam 上部署 Solidity 合约、需要一条本地链做快速迭代的合约开发者;另一类是需要在本地复现链上状态、验证运行时改动的节点与协议开发者。前者主要看 Docker 开发节点与预置账户两节,后者还需要看从源码构建、懒加载节点与测试部分。
需要先说明一点:Moonbeam 的节点程序本身是一个 Rust 二进制,Docker 只是把它打包成镜像分发。因此本文所有命令都围绕同一个可执行文件展开,区别只在于你是在容器里跑它,还是在本机直接跑它。
准备工作
Docker 环境
本地开发节点这条路只需要 Docker。镜像按每个带标签的发布版本发布,因此拉取时要指定具体的标签,而不是依赖 latest。素材中给出的示例标签是 v0.52.0,实际使用时请以官方当前发布的版本为准,版本号会随时间变化。
docker pull moonbeamfoundation/moonbeam:v0.52.0
命令中的 --network="host" 在示例里反复出现。它的作用是让容器直接使用宿主机网络,这样节点监听的 RPC 端口在宿主机上可以直接访问,省去端口映射。如果你所在的环境不方便使用 host 网络模式,就需要自行做端口映射,并相应调整你连接 RPC 的地址。
从源码构建时的环境要求
如果你要改运行时、跑单元测试或使用懒加载节点,就需要从源码构建。构建 Moonbeam 需要一个完整的 Substrate 开发环境。仓库里带有 rust-toolchain 文件,工具链版本由它固定,按仓库约定安装即可。
git clone https://github.com/moonbeam-foundation/moonbeam
cd moonbeam
克隆之后直接构建:
cargo build --release
首次构建耗时较长,素材给出的量级是约 30 分钟,具体取决于机器性能。另外要注意分支选择:直接克隆 master 分支可能得到不稳定的构建结果,如果需要稳定版本,应检出最新的发布标签。
测试相关的前置工具
仓库里同时有 Rust 单元测试和 TypeScript 集成测试。跑集成测试需要 pnpm,如果没有安装,可以用 npm 全局安装:
npm install -g pnpm
操作步骤
第一步:启动一个开发节点
开发节点是单节点模式,不需要中继链支撑,启动即可用。这是本地 dApp 开发最常用的形态。
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev
加上 --dev 之后,节点会以开发模式运行,并自动为一批众所周知的地址预置余额,具体见后文「预置开发账户」一节。
如果你只是想连上公共测试网 Moonbase Alpha 跑一个全节点,命令形态类似,但参数不同:
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --chain alphanet
这两条命令的差别值得留意:--dev 是本地单节点开发模式,--chain alphanet 是加入公共测试网。前者出块由你控制,后者跟随网络。
第二步:选择封块(sealing)模式
默认情况下,--dev 启动的节点处于即时封块模式:有交易进来就出一个块,行为类似 Ganache 的自动挖矿。对合约调试来说这通常是最省事的选择,因为发一笔交易就立刻能看到结果。
但有些场景需要不同的节奏。比如你要测试依赖时间间隔的逻辑,或者要观察多个交易被打包进不同区块时的表现,就需要按固定间隔出块:
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev --sealing 6000
这里的 6000 是毫秒,即每 6 秒出一个块。
还有一种模式是把出块与最终性完全交给 RPC 手动控制:
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev --sealing manual
手动模式下节点不会自己出块,你需要通过 RPC 触发。这种模式适合需要精确控制区块边界的测试,例如验证某个状态在特定区块高度上的取值。
三种模式的选择可以简单归纳为:日常合约开发用默认的即时封块;需要时间维度上的确定性用固定间隔;需要完全掌控区块生成时机用手动模式。
第三步:使用预置开发账户
开发模式会预置一批地址的余额。这些地址的命名大多含有字母组合「th」,用来提醒使用者它们是为以太坊兼容场景准备的。它们派生自 Substrate 的规范助记词:
bottom drive obey lake curtain smoke basket hold race lonely fit walk
下面列出各账户的地址与私钥。这些是公开的测试用密钥,只能用于本地开发,绝不能用于任何持有真实资产的场景。
| 账户 | 地址 | 私钥 |
|---|---|---|
| Alith | 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac | 0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133 |
| Baltathar | 0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0 | 0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b |
| Charleth | 0x798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc | 0x0b6e18cafb6ed99687ec547bd28139cafdd2bffe70e6b688025de6b445aa5c5b |
| Dorothy | 0x773539d4Ac0e786233D90A233654ccEE26a613D9 | 0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68 |
| Ethan | 0xFf64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB | 0x7dce9bc8babb68fec1409be38c8e1a52650206a7ed90ff956ae8a6d15eeaaef4 |
| Faith | 0xC0F0f4ab324C46e55D02D0033343B4Be8A55532d | 0xb9d2ea9a615f3165812e8d44de0d24da9bbd164b65c4f0573e1ce2c8dbd9c8df |
| Goliath | 0x7BF369283338E12C90514468aa3868A551AB2929 | 0x96b8a38e12e1a31dee1eab2fffdf9d9990045f5b37e44d8cc27766ef294acf18 |
| Heath | 0x931f3600a299fd9B24cEfB3BfF79388D19804BeA | 0x0d6dcaaef49272a5411896be8ad16c01c35d6f8c18873387b71fbc734759b0ab |
| Ida | 0xC41C5F1123ECCd5ce233578B2e7ebd5693869d73 | 0x4c42532034540267bf568198ccec4cb822a025da542861fcb146a5fab6433ff8 |
| Judith | 0x2898FE7a42Be376C8BC7AF536A940F7Fd5aDd423 | 0x94c49300a58d576011096bcb006aa06f5a91b34b4383891e8029c21dc39fbb8b |
此外还有一个专门用于测试的默认预置账户:
| 账户 | 地址 | 私钥 |
|---|---|---|
| Gerald | 0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b | 0x99b3c12287537e38c90a9219d4cb074a89a16e9cdb20bf85728ebd97c343e342 |
把这些私钥导入你常用的以太坊钱包或开发框架,就能直接对本地节点发起交易,不需要自己领水或转账。
第四步:确认链 ID
以太坊规范中有一个数值型的 Chain Id。Moonbeam 主网的 Chain Id 是 1284,这个数字对应光从 Moonbeam 到地球所需的 1284 毫秒。节点支持多个公共网络与测试网,各自的 Chain Id 如下:
| 网络 | 说明 | Chain ID | 目标中继链 |
|---|---|---|---|
| Local Parachain TestNet | 本地平行链测试网 | 1280 | — |
| Local Development TestNet | 本地开发测试网 | 1281 | — |
| Reserved for other TestNets | 保留给其他测试网 | 1282 - 1283 | — |
| Moonbeam | 主网 | 1284 | Polkadot |
| Moonriver | Kusama 上的平行链 | 1285 | Kusama |
| Moonrock | Rococo 上的平行链 | 1286 | Rococo |
| Moonbase Alpha TestNet | 公共测试网 | 1287 | Westend |
| Reserved for other public networks | 保留给其他公共网络 | 1288 - 1289 | — |
在钱包或开发框架里配置网络时,Chain Id 填错会导致签名后的交易被拒绝,这是本地调试中很常见的一类问题。用 --dev 启动的本地开发节点,对应的是本地开发测试网这一档。
另外,运行时本身也可以配置为面向不同的中继网络,所以 Chain Id 与中继链的对应关系不是写死在二进制里的常量,而是由运行时配置决定的。
第五步:运行测试
如果你在改动节点代码,跑测试是必要环节。Rust 单元测试直接执行:
cargo test
TypeScript 集成测试在 test 目录下,使用 moonwall 作为测试运行器:
cd test
pnpm i
pnpm moonwall test dev_moonbase
桥接相关的集成测试有单独的入口:
make run-bridge-integration-tests
这些测试同样在 CI 中执行,本地跑通意味着你的改动没有破坏既有行为。
第六步:用 Zombienet 启动带中继链的本地网络
开发节点是单节点、无中继链的形态。如果你需要验证平行链与中继链之间的交互,就要用 Zombienet 拉起一套本地网络。仓库提供了现成的 make 目标:
make start-zombienet-moonbeam
这条命令启动 Polkadot 中继链加 Moonbeam 平行链。如果要验证 Kusama 一侧的组合:
make start-zombienet-moonriver
这条启动 Kusama 中继链加 Moonriver 平行链。两套组合分别对应不同的运行时与中继链配置,按你要验证的目标选择。
第七步:运行懒加载节点
懒加载模式解决的是另一个问题:你不想同步整条链的状态,但又想针对生产状态做测试。这个模式让节点按需从远程归档节点拉取状态,从而省去全量同步。
前提是你已经带着想要的运行时改动构建了节点:
make release-build
然后启动懒加载节点:
make start-lazy-loading-node
这条命令会做四件事:建立运行时覆盖目录 .lazy-loading/wasm-runtime-overrides;把你构建出的运行时 WASM 复制进覆盖目录;生成一份默认的状态覆盖配置 .lazy-loading/state-overrides.json;最后连接远程 RPC 端点启动节点。
默认配置连接的是 Moonbeam 网络。要换网络或换 RPC 端点,通过环境变量指定:
RPC=<远程归档节点地址> RUNTIME=moonriver make start-lazy-loading-node
可用的配置项有两个:
RPC:远程归档节点的 RPC 端点,默认指向 Moonbeam 网络。RUNTIME:使用的运行时,可选moonbeam、moonriver或moonbase,默认是moonbeam。
状态覆盖文件 .lazy-loading/state-overrides.json 允许你覆盖远程状态中的特定存储值。它的用途是在不改动真实链上状态的前提下,测试运行时升级或自定义配置。例如你想验证某个存储项取不同值时运行时的行为,就可以在本地覆盖它,而不必去动链上数据。
一个完整示例
下面把前面几节串起来,走一遍从零到能发交易的最小流程。
1. 拉取镜像并启动开发节点
docker pull moonbeamfoundation/moonbeam:v0.52.0
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev
节点启动后处于即时封块模式,有交易就出块。
2. 在钱包或开发框架中配置网络
RPC 地址指向本机节点暴露的端口,Chain Id 使用本地开发测试网对应的值。具体端口以节点启动日志中的输出为准。
3. 导入预置账户
以 Alith 为例,导入它的私钥:
0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133
对应地址是 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac。这个账户在开发模式下已有余额,可以直接发起交易。
4. 部署一个合约并观察出块
用你惯用的工具把合约部署到这条本地链上。由于是即时封块,交易发出后立刻会被打包,不需要等待固定间隔。
5. 需要固定节奏时切换封块模式
如果后续测试依赖时间间隔,停掉节点,改用固定间隔重新启动:
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev --sealing 6000
此时每 6 秒出一个块,交易会等待下一个出块时点被打包。
6. 需要精确控制区块边界时改用手动模式
docker run --network="host" moonbeamfoundation/moonbeam:v0.52.0 --dev --sealing manual
节点不再自动出块,出块与最终性由你通过 RPC 触发。这样你可以精确决定某个状态出现在哪个区块高度上。
整个流程中,唯一会变化的是启动参数,账户、Chain Id 与合约代码都不需要改。这也是把开发节点放在 Docker 里的好处:换模式只是换一条命令。
注意事项
预置私钥只能用于本地开发
前文列出的所有地址与私钥都是公开的,派生自一条公开的规范助记词。任何拿到这些私钥的人都能控制对应地址。它们的存在意义是让本地开发免去领水与转账,一旦用于持有真实资产的网络,资产会立即处于任何人都能转走的状态。
master 分支可能不稳定
直接克隆 master 分支构建,可能得到不稳定的结果。需要稳定版本时应检出最新的发布标签。Docker 镜像同理,按带标签的发布版本拉取,不要依赖浮动标签。
首次构建耗时较长
从源码构建的首次编译大约需要 30 分钟,这是正常现象,不是卡死。后续增量构建会快很多。
host 网络模式的适用性
示例命令统一使用 --network="host"。这个模式在部分平台上行为不同,如果你的环境不支持,需要改用端口映射,并相应调整连接 RPC 时使用的地址。这一点在跨平台开发时容易踩坑。
Chain Id 必须与目标网络一致
Chain Id 填错会导致交易签名校验失败。本地开发、公共测试网、主网各有不同的 Chain Id,配置时对照前文的表格确认。运行时也可以配置为面向不同的中继网络,所以不要假设某个 Chain Id 在所有构建中都固定不变。
懒加载节点依赖远程归档节点
懒加载模式按需从远程归档节点拉取状态,因此远程端点的可用性与响应速度直接影响本地节点的表现。默认连接的是 Moonbeam 网络,换网络时要同时确认 RPC 与 RUNTIME 两个变量匹配,否则会出现运行时与状态不一致的问题。
版本与镜像标签以官方当前信息为准
本文示例中出现的镜像标签、命令参数与配置项名称都可能随版本变化。实际动手前,请以官方当前发布的版本与文档为准,不要直接照抄示例中的版本号。