HyperLedger Fabric学习(二)——使用Docker镜像编译Fabric(1.0.4)源码并搭建简单测试网络

简述

本文主要内容是使用docker镜像编译Fabric源码,并使用编译生成的程序构建一个只有1个Orderer、1个Peer的简单网络,以此作为后续学习的基础。
本文代码使用fabric v1.0.4、docker镜像是yeasy/hyperledger-fabric:1.0.4,我们可以从 Docker Hub上看到该镜像的信息,基于golang镜像构建,给我们安装好了编译Fabric的环境依赖、gotools等,可以给我们省不少事情。

搭建编译环境、并编译

下载Fabric源码

第一步是下载我们将要进行编译的Fabric源码。在这里说来真是觉得Fabric文档写的很详细。基本上根据文档来都能有所收获。废话少说我们通过以下命令下载源码,并将代码版本切到1.0.4

~$:git clone https://github.com/hyperledger/fabric.git
~$:cd fabric
~/fabric$:git tag
~/fabric$:git checkout v1.0.4

下载yeasy/hyperledger-fabric:1.0.4镜像

这一步没什么说的,需要强调的一点是一定要使用国内的镜像站(如阿里镜像),不然的话镜像下载超慢,你可能在这一步就直接放弃了。

docker pull yeasy/hyperledger-fabric:1.0.4

编译Fabric源代码

事实上在yeasy/hyperledger-fabric镜像当中已经给我们装好了Fabric了(在/go路径下),但我们不直接使用它提供的,而是使用我们在上边下载好的源文件编译重新生成并安装。具体步骤如下:
首先我们需要一个docker-compose配置文件,具体文件内容如下:

version: '2'

services:
  compile:
    container_name: compile
    image: yeasy/hyperledger-fabric:1.0.4    
    command: /bin/bash -c 'sleep 6000000'
    working_dir: /go/src/github.com/hyperledger/fabric
    volumes:
      - ~/bin:/go/bin
      - ~/fabric:/go/src/github.com/hyperledger/fabric     

我们将该文件命名为docker-compose-compile.yaml 并将其放在~/目录下。
启动docker镜像

~$:docker-compose -f ~/docker-compose-compile.yaml up -d

进入docker镜像并编译(以编译orderer模块为例)

~$:docker exec -it compile bash

#进入docker镜像交互界面后
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# cd orderer
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# go build
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# go install

以上步骤成功的话你应该可以在镜像的/go/bin目录下看到新生成的orderer可执行程序,并且在本机~/bin目录下也可以看到编译生成的orderer文件,此外我们还需要生成peer模块,进入该peer目录go build,go install即可

以上方法主要是利用了docker数据卷的功能,我们在本地修改代码后,镜像当中可以立即看到被修改内容,只需要在镜像中重新编译就可以使修改后的代码生效。

搭建简单测试网络

生成配置文件

接下来我们搭建一个仅有一个Orderer和一个Peer的网络。
首先们们需要编译生成两个工具:cryptogen生成加密证书,configtxgen生成交易配置(详情请查看官方文档)。
这两个工具在镜像中的目录分别为/go/src/github.com/hyperledger/fabric/common/tools/cryptogen/go/src/github.com/hyperledger/fabric/common/configtx/tool/configtxgen,分别进入其中执行go build,go install 即可在镜像的/go/bin目录(对应本机的~/bin目录)下生成相应的可执行文件。
接下来我们需要准备两个配置文件。
先新建一个目录用于保存我们所有的配置文件

~$:mkdir mynet
~$:cd mynet

mynet目录下新建crypto-config.yaml这是一个生成机构加密证书的配置文件,具体内容如下


OrdererOrgs:
  - Name: Orderer
    Domain: orderer.com
    Specs:
      - Hostname: orderer0
PeerOrgs:
  - Name: Org1
    Domain: peer.com
    Template:
      Count: 1
    Users:
      Count: 1

我们可以看到其内容根据字面意思理解就是一个Orderer机构,一个Peer机构,Peer机构里有一个节点(Template.Count:1) 一个用户(Users.Count:1)

我们可以使用~/bin/cryptogen 工具来生成证书如下:

~/mynet$:~/bin/cryptogen generate --config=./crypto-config.yaml
peer.com

在当前目录下可以看到生成了一个crypto-config文件夹,里面包含两个文件夹分别是ordererOrganizations, peerOrganizations

接下来我们需要使用configtxgen生成交易的配置。需要一个配置文件configtx.yaml内容如下


Profiles:
    OneOrgsOrdererGenesis:
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
    OneOrgsChannel:
        Consortium: SampleConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1

Organizations:
    - &OrdererOrg      
        Name: OrdererOrg
        ID: OrdererMSP      
        MSPDir: crypto-config/ordererOrganizations/orderer.com/msp
    - &Org1    
        Name: Org1MSP     
        ID: Org1MSP
        MSPDir: crypto-config/peerOrganizations/peer.com/msp
        AnchorPeers:      
            - Host: peer0.peer.com
              Port: 7051
Orderer: &OrdererDefaults
    OrdererType: solo
    Addresses:
        - orderer0.orderer.com:7050
    BatchTimeout: 2s
    BatchSize:     
        MaxMessageCount: 10      
        AbsoluteMaxBytes: 99 MB      
        PreferredMaxBytes: 512 KB
    Kafka:     
        Brokers:
            - 127.0.0.1:9092
    Organizations:
Application: &ApplicationDefaults
    Organizations:

建议查看一下官方文档。
执行如下命令

~/mynet$:export FABRIC_CFG_PATH=$PWD
~/mynet$:mkdir channel-artifacts
~/mynet$:~/bin/configtxgen -profile OneOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block  #产生创世块
~/mynet$:export CHANNEL_NAME=mychannel
~/mynet$:~/bin/configtxgen -profile OneOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME  #产生channel配置
~/mynet$:~/bin/configtxgen -profile OneOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP #机构1 AnchorPeer配置

成功执行以上命令后会在~/mynet/channel-artifacts目录下生成以下三个文件

channel.tx
genesis.block
Org1MSPanchors.tx

启动Orderer节点

为了更深入的学习我们分别启动Orderer节点和Peer节点,首先是Orderer ,我们需要准备一个docker-compose的配置文件
内容如下

version: '2'

networks:
  my_net:


services:
  orderer0.orderer.com:
    container_name: orderer0.orderer.com
    image: yeasy/hyperledger-fabric:1.0.4
    environment:
      - ORDERER_GENERAL_LOGLEVEL=debug
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/root/Workspace/mynet/channel-artifacts/genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp
      - GRPC_TRACE=all=true
      - GRPC_VERBOSITY=debug

          # enabled TLS
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/ca.crt]

    command: /bin/bash -c 'sleep 6000000'
    working_dir: /root/Workspace/mynet
    volumes:
      - ./:/root/Workspace/mynet
      - ~/bin:/go/bin
      - ~/fabric:/go/src/github.com/hyperledger/fabric
    ports:
      - 7050:7050
    networks:
      - my_net

文件我们保存为docker-compose-orderer.yaml 使用docker-compose启动

~/mynet$:docker-compose -f docker-compose-orderer.yaml up -d
~/mynet$:docker exec -it orderer0.orderer.com bash
root@4c05353b5007:/root/Workspace/mynet#orderer  

一切正常的情况下我们可以看到类似于如下输出

... ...
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0be Returning policy Readers for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0bf As expected, current configuration has policy '/Channel/Readers'
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0c0 Returning policy Writers for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0c1 As expected, current configuration has policy '/Channel/Writers'
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0c2 Returning policy Orderer/BlockValidation for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0c3 As expected, current configuration has policy '/Channel/Orderer/BlockValidation'
2018-03-18 01:27:30.335 UTC [fsblkstorage] retrieveBlockByNumber -> DEBU 0c4 retrieveBlockByNumber() - blockNum = [0]
2018-03-18 01:27:30.336 UTC [fsblkstorage] newBlockfileStream -> DEBU 0c5 newBlockfileStream(): filePath=[/var/hyperledger/production/orderer/chains/testchainid/blockfile_000000], startOffset=[0]
2018-03-18 01:27:30.337 UTC [fsblkstorage] nextBlockBytesAndPlacementInfo -> DEBU 0c6 Remaining bytes=[6357], Going to peek [8] bytes
2018-03-18 01:27:30.337 UTC [fsblkstorage] nextBlockBytesAndPlacementInfo -> DEBU 0c7 Returning blockbytes - length=[6355], placementInfo={fileNum=[0], startOffset=[0], bytesOffset=[2]}
2018-03-18 01:27:30.337 UTC [orderer/multichain] newChainSupport -> DEBU 0c8 [channel: testchainid] Retrieved metadata for tip of chain (blockNumber=0, lastConfig=0, lastConfigSeq=0):
2018-03-18 01:27:30.337 UTC [orderer/multichain] NewManagerImpl -> INFO 0c9 Starting with system channel testchainid and orderer type solo
2018-03-18 01:27:30.337 UTC [orderer/main] main -> INFO 0ca Beginning to serve requests

至此我们自己编译生成的orderer节点就算启动成功了。

启动Peer节点

准备docker-compose-peer.yaml 文件,内容如下

version: '2'

networks:
  my_net:

services:
  peer0.peer.com:
    container_name: peer0.peer.com
    image: yeasy/hyperledger-fabric:1.0.4
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      #- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn
      #- CORE_LOGGING_LEVEL=ERROR
      - CORE_LOGGING_LEVEL=DEBUG      
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_PROFILE_ENABLED=true

      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/ca.crt

      - CORE_PEER_ID=peer0.peer.com
      - CORE_PEER_ADDRESS=peer0.peer.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.peer.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_MSPCONFIGPATH=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/users/Admin@peer.com/msp

    command: /bin/bash -c 'sleep 6000000'
    working_dir: /root/Workspace/mynet
    volumes:
      - ./:/root/Workspace/mynet
      - ~/bin:/go/bin
      - ~/fabric:/go/src/github.com/hyperledger/fabric
    ports:
      - 7051:7051
      - 7053:7053
    networks:
      - my_net

启动Peer节点

~/mynet:docker-compose -f docker-compose-peer.yaml up -d
~/mynet:docker exec -it peer0.peer.com bash
root@6f8bea5ddecd:/root/Workspace/mynet# peer node start

成功后应该会出现如下输

... ...
2018-03-18 01:49:04.704 UTC [nodeCmd] serve -> INFO 192 Starting peer with ID=[name:"peer0.org1.example.com" ], network ID=[dev], address=[peer0.org1.example.com:7051]
2018-03-18 01:49:04.704 UTC [nodeCmd] serve -> INFO 193 Started peer with ID=[name:"peer0.org1.example.com" ], network ID=[dev], address=[peer0.org1.example.com:7051]
2018-03-18 01:49:04.704 UTC [flogging] setModuleLevel -> DEBU 194 Module 'msp/identity' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 195 Module 'msp' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 196 Module 'configvalues/msp' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 197 Module 'peer/gossip/sa' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 198 Module 'gossip/election' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 199 Module 'gossip/gossip' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19a Module 'gossip/service' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19b Module 'gossip/pull' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19c Module 'gossip/state' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19d Module 'peer/gossip/mcs' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19e Module 'gossip/comm' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19f Module 'gossip/discovery' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a0 Module 'ledgermgmt' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a1 Module 'kvledger' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a2 Module 'kvledger.util' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a3 Module 'cauthdsl' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a4 Module 'policies' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a5 Module 'grpc' logger enabled for log level 'ERROR'
2018-03-18 01:49:04.706 UTC [nodeCmd] func5 -> INFO 1a6 Starting profiling server with listenAddress = 0.0.0.0:6060

构建Fabric网络

创建并加入Channel

这一步可是废了我好大的力气,如果在创建Channel的时候不成功就好好检查上边的配置吧,我修改了好几遍才最终成功。

root@6f8bea5ddecd:/root/Workspace/mynet# export CHANNEL_NAME=mychannel
root@6f8bea5ddecd:/root/Workspace/mynet# peer channel create -o orderer0.orderer.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem 
root@6f8bea5ddecd:/root/Workspace/mynet# peer channel join -b mychannel.block

更新锚节点配置

peer channel update -o orderer0.orderer.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem

输出为

2018-04-03 16:01:10.535 UTC [msp] GetLocalMSP -> DEBU 00a Returning existing local MSP
2018-04-03 16:01:10.535 UTC [msp] GetDefaultSigningIdentity -> DEBU 00b Obtaining default signing identity
2018-04-03 16:01:10.535 UTC [msp] GetLocalMSP -> DEBU 00c Returning existing local MSP
2018-04-03 16:01:10.535 UTC [msp] GetDefaultSigningIdentity -> DEBU 00d Obtaining default signing identity
2018-04-03 16:01:10.535 UTC [msp/identity] Sign -> DEBU 00e Sign: plaintext: 0AA2060A1508021A0608C6CA8ED60522...7DE2990B6D1B864A669BA59D3D159989
2018-04-03 16:01:10.535 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 126C57735E1A67D918AB54A61FD1009A5390A3351012B444764FB308A1DB38B6
2018-04-03 16:01:10.558 UTC [main] main -> INFO 010 Exiting.....

部署chaincode

在fabric/example/chaincode下有很多样例合约,我们为了演示,选取其中较简单的map进行部署测试

peer chaincode install  -p github.com/hyperledger/fabric/examples/chaincode/go/map -n mycc -v 0

得到如下输出

2018-03-18 13:03:15.015 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-03-18 13:03:15.015 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-03-18 13:03:15.015 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-03-18 13:03:15.015 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-03-18 13:03:15.073 UTC [golang-platform] getCodeFromFS -> DEBU 005 getCodeFromFS github.com/hyperledger/fabric/examples/chaincode/go/map
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 006 Discarding GOROOT package encoding/json
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 007 Discarding GOROOT package fmt
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 008 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 009 Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package strconv
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 00b Discarding GOROOT package time
2018-03-18 13:03:15.353 UTC [golang-platform] GetDeploymentPayload -> DEBU 00c done
2018-03-18 13:03:15.398 UTC [msp/identity] Sign -> DEBU 00d Sign: plaintext: 0AE9060A5C08031A0C0893C7B9D50510...1F70FC270000FFFFD9315A97001E0000 
2018-03-18 13:03:15.398 UTC [msp/identity] Sign -> DEBU 00e Sign: digest: 65B8E2ECB1B647DA9B1E93048E874ECCCA2E6BBCC3A52B0EB77EB6B7D76049D2 
2018-03-18 13:03:15.403 UTC [chaincodeCmd] install -> DEBU 00f Installed remotely response:200 payload:"OK" > 
2018-03-18 13:03:15.403 UTC [main] main -> INFO 010 Exiting.....

实例化Chaincode

peer chaincode instantiate -o orderer0.orderer.com:7050 --tls true --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem -C $CHANNEL_NAME -n mycc -v 0 -c '{"Args":["a","10"]}'

问题汇总

  • 实例化Chaincode时遇到以下错误
Error: Error endorsing chaincode: rpc error: code = Unknown desc = Error starting container: Failed to generate platform-specific docker build: Failed to pull /fabric-ccenv:x86_64-development build: API error (400): {"message":"invalid reference format"}
  • 使用gdb调试代码
    大家可能在docker镜像中调试代码时发现gdb的断点不起作用。需要修改相应的docker-compose.yaml文件。在其中添加
security_opt:  
      - seccomp=unconfined

这样就可以正常使用gdb调试了。

你可能感兴趣的:(HyperLedger,Fabric)