以太坊作为目前最知名的智能合约平台之一,其开发、测试和部署过程往往需要特定的网络环境和节点支持,Docker作为一种轻量级、可移植的容器化技术,能够极大地简化以太坊节点的部署和管理,让开发者能够快速搭建一致、隔离的开发环境,本文将详细介绍如何使用Docker搭建以太坊开发环境,包括运行以太坊客户端节点、私有链测试等常见场景。

为什么选择Docker搭建以太坊环境

在开始之前,我们先了解一下为何使用Docker搭建以太坊环境具有优势:

  1. 环境一致性:Docker确保了开发、测试和生产环境的高度一致性,避免了“在我机器上能跑”的问题。
  2. 快速部署与销毁:通过Docker镜像,可以在几分钟内启动一个全新的以太坊节点,测试完成后也可快速销毁,节省资源。
  3. 资源隔离:每个Docker容器都是独立的运行环境,互不干扰,便于同时运行多个不同配置的节点。
  4. 简化依赖管理:Docker镜像已经封装了以太坊客户端运行所需的依赖,无需手动配置复杂的编译环境和运行库。
  5. 版本管理便捷:可以轻松切换不同版本的以太坊客户端(如Geth, Parity等)进行测试和开发。

准备工作

在开始搭建之前,请确保你的系统已经安装了以下软件:

  1. Docker:请根据你的操作系统(Windows, macOS, Linux)从Docker官网下载并安装最新版本的Docker,对于Windows和macOS,推荐安装Docker Desktop。
  2. Docker Compose(可选,但推荐):用于定义和运行多容器Docker应用程序的应用,通常Docker Desktop会自带,Linux系统可能需要单独安装。
  3. 基本的命令行操作知识:我们将使用命令行来与Docker交互。

使用Docker运行官方以太坊客户端(以Geth为例)

Geth是以太坊官方实现的Go语言客户端,功能强大,使用广泛,我们可以直接从Docker Hub拉取Geth官方镜像来运行一个节点。

拉取Geth Docker镜像

打开终端或命令提示符,执行以下命令拉取最新版的Geth镜像:

docker pull ethereum/client-go:latest

如果你需要特定版本,可以将latest替换为具体的版本标签,例如v1.10.26

启动一个以太坊主网节点(同步模式)

运行一个同步到以太坊主网的节点,这需要较长的时间和较多的磁盘空间(数百GB)。

docker run -d --name geth-mainnet-node -p 8545:8545 -p 30303:30303/udp -p 30303:30303/tcp ethereum/client-go:latest --http --http.addr "0.0.0.0" --http.vhosts "*" --http.api "eth,net,web3,personal" --ws --ws.addr "0.0.0.0" --ws.api "eth,net,web3" --ws.origins "*"

命令解释:

  • docker run -d: 在后台运行容器。
  • --name geth-mainnet-node: 为容器指定一个名称,方便后续管理。
  • -p 8545:8545: 将容器的8545端口(HTTP-RPC端口)映射到主机的8545端口,方便通过API或工具(如Postman, Remix IDE)连接。
  • -p 30303:30303/udp -p 30303:30303/tcp: 将容器的P2P发现端口(30303)映射到主机,支持TCP和UDP协议。
  • ethereum/client-go:latest: 使用的Geth镜像。
  • --http: 启用HTTP-RPC服务。
  • --http.addr "0.0.0.0": HTTP-RPC服务监听所有网络接口。
  • --http.vhosts "*": 允许所有主机名的HTTP请求(开发环境使用,生产环境需谨慎配置)。
  • --http.api "eth,net,web3,personal": 暴露的HTTP API接口。
  • --ws: 启用WebSocket-RPC服务。
  • --ws.addr "0.0.0.0": WebSocket-RPC服务监听所有网络接口。
  • --ws.api "eth,net,web3": 暴露的WebSocket API接口。
  • --ws.origins "*": 允许所有来源的WebSocket连接(开发环境使用,生产环境需谨慎配置)。

启动后,Geth会开始同步以太坊主网数据,你可以通过以下命令查看容器日志:

docker logs -f geth-mainnet-node

连接到节点

同步完成后,你可以使用各种工具连接到这个节点,使用curl测试HTTP-RPC:

curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545

如果返回最新的区块号,则表示连接成功。

使用Docker Compose搭建私有测试链

对于开发和测试,我们通常不需要同步庞大的主网数据,而是搭建一个本地的私有测试链,使用Docker Compose可以更方便地管理多节点私有链。

创建项目目录和docker-compose.
随机配图
yml文件

mkdir eth-private-chain
cd eth-private-chain
touch docker-compose.yml

编写docker-compose.yml文件

编辑docker-compose.yml如下(以启动3个节点的私有链为例):

version: '3'
services:
  node1:
    image: ethereum/client-go:latest
    container_name: geth-node1
    ports:
      - "30301:30303/udp"
      - "30301:30303/tcp"
      - "8545:8545"
    volumes:
      - ./node1/data:/root/.ethereum
    networks:
      - eth-network
    command: >
      --dev
      --datadir /root/.ethereum
      --port 30303
      --http
      --http.addr "0.0.0.0"
      --http.api "eth,net,web3,miner,admin"
      --http.corsdomain "*"
      --ws
      --ws.addr "0.0.0.0"
      --ws.api "eth,net,web3,miner,admin"
      --ws.origins "*"
      --gasprice "1"
      --miner.etherbase "0xYourNode1AccountAddress" # 替换为你的节点1地址
      --unlock "0xYourNode1AccountAddress" # 解锁账户
      --password /dev/null # 使用空密码,仅开发环境
  node2:
    image: ethereum/client-go:latest
    container_name: geth-node2
    ports:
      - "30302:30303/udp"
      - "30302:30303/tcp"
      - "8546:8545"
    volumes:
      - ./node2/data:/root/.ethereum
    networks:
      - eth-network
    command: >
      --dev
      --datadir /root/.ethereum
      --port 30303
      --http
      --http.addr "0.0.0.0"
      --http.api "eth,net,web3,miner,admin"
      --http.corsdomain "*"
      --ws
      --ws.addr "0.0.0.0"
      --ws.api "eth,net,web3,miner,admin"
      --ws.origins "*"
      --gasprice "1"
      --miner.etherbase "0xYourNode2AccountAddress" # 替换为你的节点2地址
      --unlock "0xYourNode2AccountAddress" # 解锁账户
      --password /dev/null
  node3:
    image: ethereum/client-go:latest
    container_name: geth-node3
    ports:
      - "30303:30303/udp"
      - "30303:30303/tcp"
      - "8547:8545"
    volumes:
      - ./node3/data:/root/.ethereum
    networks:
      - eth-network
    command: >
      --dev
      --datadir /root/.ethereum
      --port 30303
      --http
      --http.addr "0.0.0.0"
      --http.api "eth,net,web3,miner,admin"
      --http.corsdomain "*"
      --ws
      --ws.addr "0.0.0.0"
      --ws.api "eth,net,web3,miner,admin"
      --ws.origins "*"
      --gasprice "1"
      --miner.etherbase "0xYourNode