1、导言:

       为了学习fabric底层运行原理,这两天基于fabric 1.4版本手动部署了一个多机网络,期间遇到了很多各种各样的问题,同时也一个一个解决了,最终成功把多机fabric网络部署起来,也进行了一些简单交易测试。整个部署过程加深了本人的fabric网络的认识,再次特地把整个过程记录下来,方便以后复习;另外希望能帮助到有类似需求的人们。

 

2、准备工作

知识准备

       手动搭建Fabric环境需要使用到docker和fabric命令;因此,如果是新手(老手跳过)最好是先了解docker和docker的使用,以及fabric对应的使用方法,如peer、configtxgen等。

 

设备准备

       Fabric 1.4使用raft共识,其共识中同步的节点必须是奇数,因为整个共识网络中每个节点都是follower,当网络中没有leader时,他们就会变成candidator,此时需要在网络中选出leader,而选择leader要达成一致的过程需要网络中有n/2+1个节点达成一致,所以需要奇数个同步节点。

       由此,本次fabric 1.4网络环境搭建,包括2个组织、5个orderer节点和4个peer节点,同时准备了5台主机,具体分配如下:

主机节点分布

地址

orderer0.example.com

peer0.org1.example.com

couchdb0,cli

ca_peerOrg1

192.168.128.81

orderer1.example.com

peer1.org1.example.com

cli

192.168.128.75

orderer2.example.com

peer2.org1.example.com

cli

192.168.128.76

orderer3.example.com

peer3.org1.example.com

cli

192.168.128.77

orderer4.example.com

cli

192.168.128.63

 

环境准备

       环境准备包括docker和go安装与配置,这些与本次实际内容无关,因此这里不做介绍,使用者自行搭建,这里给出本人的go环境配置选项:

export GOPATH=$HOME/gopath

export GOBIN=$GOPATH/bin

export PATH=$PATH:$GOBIN

 

获取镜像

1)克隆fabric-samples

git clone git@github.com:hyperledger/fabric-samples.git

2) 进入fabric-samples/scripts,为了获取最新的镜像,打开bootstrap.sh把版本信息修改成最新版本:1.4.0->1.4.1,0.4.14->0.4.15。

3)执行bootstrap.sh获取fabric最新docker镜像,以及相关命令工具。执行完成后,或在fabric-samples/bin目录下得到编译好的命令,把这些命令拷贝到GOBIN目录或者用户bin目录下,这样就可以全局使用这些命令了。用户也可以通过编译源码方式得到这些命令,详见:hyperledger fabric源码编译(手把手教编译fabric源码

       另外,bootstrap.sh脚本也是集合了各种拉取镜像的命令来获取对应镜像的,用户也可以通过具体的命令来获取对应的docker镜像,如:

拉取peer镜像

docker pull hyperledger/fabric-peer:1.4.1   #拉取

docker tag hyperledger/fabric-peer:1.4.1 hyperledger/fabric-peer:latest  #标记为hyperledger/fabric-peer:latest

 

       到此,fabric网络环境的准备工作已经完成,接下来我们开始搭建fabric网络。

 

3、Fabric网络搭建

3.1 前期准备

网络搭建说明

  1. 整个网络搭建需要多个配置文件,包括生成节点证书配置文件,生成系统创世块配置文件,peer、cli、orderer、db配置文件,网络搭建前首先根据实际需要编写好这些配置文件,这些配置文件在fabric-samples/first-network目录下都有对应的,可以根据这些配置文件来编写自己的配置文件。
  2. 本例给出配置文件,但不做详细说明,想对配置文件具体配置项了解的请到另一遍博文查看:《hyperledger fabric配置文件详细分析
  3. 搭建fabric网络的工作路径是$HOME/env/raft-example,没有特殊说明都默认是在该目录下操作。

 

工作目录结构

raft-example            #主工作目录

├── chaincode        #存放chaincode源码

├── channel-artifacts  #存放配置文件生产的创世块,chaincode二进制文件等。

├── crypto-config     #节点证书存放位置

└── scripts           #相关操作脚本

 

3.2 第一台主机(192.168.128.81)

构建节点证书

准备生成节点证书配置文件crypto-config.yaml,内容如下:

OrdererOrgs:
  - Name: Orderer
    Domain: example.com    #域名
    Specs:
      - Hostname: orderer0
      - Hostname: orderer1
      - Hostname: orderer2
      - Hostname: orderer3
      - Hostname: orderer4
PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true 
    Template:
      Count: 4   #生成4个peer
    Users:
      Count: 4   #生成4个普通user

 

执行命令cryptogen generate --config ./crypto-config.yaml生成各个节点的证书,生成证书结构如下:

crypto-config
├── ordererOrganizations
│   └── example.com
│       ├── ca
│       ├── msp
│       │   ├── admincerts
│       │   ├── cacerts
│       │   └── tlscacerts
│       ├── orderers
│       │   ├── orderer0.example.com
│       │   │   ├── msp
│       │   │   │   ├── admincerts
│       │   │   │   ├── cacerts
│       │   │   │   ├── keystore
│       │   │   │   ├── signcerts
│       │   │   │   └── tlscacerts
│       │   │   └── tls
│       │   ├── orderer1.example.com
│       │   │   ├── msp
│       │   │   │   ├── admincerts
│       │   │   │   ├── cacerts
│       │   │   │   ├── keystore
│       │   │   │   ├── signcerts
│       │   │   │   └── tlscacerts
│       │   │   └── tls
│       │   ├── orderer2.example.com
│       │   │   ├── msp
│       │   │   │   ├── admincerts
│       │   │   │   ├── cacerts
│       │   │   │   ├── keystore
│       │   │   │   ├── signcerts
│       │   │   │   └── tlscacerts
│       │   │   └── tls
│       │   ├── orderer3.example.com
│       │   │   ├── msp
│       │   │   │   ├── admincerts
│       │   │   │   ├── cacerts
│       │   │   │   ├── keystore
│       │   │   │   ├── signcerts
│       │   │   │   └── tlscacerts
│       │   │   └── tls
│       │   └── orderer4.example.com
│       │       ├── msp
│       │       │   ├── admincerts
│       │       │   ├── cacerts
│       │       │   ├── keystore
│       │       │   ├── signcerts
│       │       │   └── tlscacerts
│       │       └── tls
│       ├── tlsca
│       └── users
│           └── Admin@example.com
│               ├── msp
│               │   ├── admincerts
│               │   ├── cacerts
│               │   ├── keystore
│               │   ├── signcerts
│               │   └── tlscacerts
│               └── tls
└── peerOrganizations
    └── org1.example.com
        ├── ca
        ├── msp
        │   ├── admincerts
        │   ├── cacerts
        │   └── tlscacerts
        ├── peers
        │   ├── peer0.org1.example.com
        │   │   ├── msp
        │   │   │   ├── admincerts
        │   │   │   ├── cacerts
        │   │   │   ├── keystore
        │   │   │   ├── signcerts
        │   │   │   └── tlscacerts
        │   │   └── tls
        │   ├── peer1.org1.example.com
        │   │   ├── msp
        │   │   │   ├── admincerts
        │   │   │   ├── cacerts
        │   │   │   ├── keystore
        │   │   │   ├── signcerts
        │   │   │   └── tlscacerts
        │   │   └── tls
        │   ├── peer2.org1.example.com
        │   │   ├── msp
        │   │   │   ├── admincerts
        │   │   │   ├── cacerts
        │   │   │   ├── keystore
        │   │   │   ├── signcerts
        │   │   │   └── tlscacerts
        │   │   └── tls
        │   └── peer3.org1.example.com
        │       ├── msp
        │       │   ├── admincerts
        │       │   ├── cacerts
        │       │   ├── keystore
        │       │   ├── signcerts
        │       │   └── tlscacerts
        │       └── tls
        ├── tlsca
        └── users
            ├── Admin@org1.example.com
            │   ├── msp
            │   │   ├── admincerts
            │   │   ├── cacerts
            │   │   ├── keystore
            │   │   ├── signcerts
            │   │   └── tlscacerts
            │   └── tls
            ├── User1@org1.example.com
            │   ├── msp
            │   │   ├── admincerts
            │   │   ├── cacerts
            │   │   ├── keystore
            │   │   ├── signcerts
            │   │   └── tlscacerts
            │   └── tls
            ├── User2@org1.example.com
            │   ├── msp
            │   │   ├── admincerts
            │   │   ├── cacerts
            │   │   ├── keystore
            │   │   ├── signcerts
            │   │   └── tlscacerts
            │   └── tls
            ├── User3@org1.example.com
            │   ├── msp
            │   │   ├── admincerts
            │   │   ├── cacerts
            │   │   ├── keystore
            │   │   ├── signcerts
            │   │   └── tlscacerts
            │   └── tls
            └── User4@org1.example.com
                ├── msp
                │   ├── admincerts
                │   ├── cacerts
                │   ├── keystore
                │   ├── signcerts
                │   └── tlscacerts
                └── tls

构建系统创世块

准备生成系统创世块配置文件configtx.yaml。

configtx.yaml内容如下:

Organizations:

    - &OrdererOrg

        Name: OrdererOrg

        ID: OrdererMSP

        MSPDir: crypto-config/ordererOrganizations/example.com/msp

        Policies:

          Readers:

              Type: Signature

              Rule: "OR('OrdererMSP.member')"

          Writers:

              Type: Signature

              Rule: "OR('OrdererMSP.member')"

          Admins:

              Type: Signature

              Rule: "OR('OrdererMSP.admin')"

    - &Org1

        Name: Org1MSP

        ID: Org1MSP

        MSPDir: crypto-config/peerOrganizations/org1.example.com/msp

        AnchorPeers:

            - Host: peer0.org1.example.com

              Port: 7051

        Policies:

          Readers:

              Type: Signature

              Rule: "OR('Org1MSP.admin','Org1MSP.peer','Org1MSP.client')"

          Writers:

              Type: Signature

              Rule: "OR('Org1MSP.admin','Org1MSP.client')"

          Admins:

              Type: Signature

              Rule: "OR('Org1MSP.admin')"

Capabilities:

    Channel: &ChannelCapabilities

        V1_3: true

Orderer: &OrdererCapabilities

        V1_1: true

Application: &ApplicationCapabilities

        V1_3: true

        V1_2: false

        V1_1: false

Application: &ApplicationDefaults

    Organizations:

    Policies:

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"

    Capabilities:

        <<: *ApplicationCapabilities

Orderer: &OrdererDefaults

    OrdererType: solo

    Addresses:

        - orderer0.example.com:7050

    BatchTimeout: 2s

    BatchSize:

        MaxMessageCount: 200

        AbsoluteMaxBytes: 2 MB

        PreferredMaxBytes: 512 KB

    Kafka:

        Brokers:

        - 127.0.0.1:9092

    Organizations:

    Policies:

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"

        BlockValidation:

            Type: ImplicitMeta

            Rule: "ANY Writers"

Channel: &ChannelDefaults

    Policies:

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"

    Capabilities:

        <<: *ChannelCapabilities

Profiles:

    TwoOrgsOrdererGenesis:

        <<: *ChannelDefaults

        Capabilities:

            <<: *ChannelCapabilities

        Orderer:

            <<: *OrdererDefaults

            OrdererType: etcdraft

            EtcdRaft:

                Consenters:

                - Host: orderer0.example.com

                  Port: 7050

                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt

                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt

                - Host: orderer1.example.com

                  Port: 7050

                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt

                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt

                - Host: orderer2.example.com

                  Port: 7050

                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt

                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt

                - Host: orderer3.example.com

                  Port: 7050

                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt

                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt

                - Host: orderer4.example.com

                  Port: 8050

                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt

                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt

            Addresses:

                - orderer0.example.com:7050

                - orderer1.example.com:7050

                - orderer2.example.com:7050

                - orderer3.example.com:7050

                - orderer4.example.com:8050

            Organizations:

            - *OrdererOrg

            Capabilities:

                <<: *OrdererCapabilities

        Application:

            <<: *ApplicationDefaults

            Organizations:

            - <<: *OrdererOrg

        Consortiums:

            SampleConsortium:

                Organizations:

                    - *Org1

    TwoOrgsChannel:

        Consortium: SampleConsortium

        <<: *ChannelDefaults

        Application:

            <<: *ApplicationDefaults

            Organizations:

                - *Org1

            Capabilities:

                <<: *ApplicationCapabilities

该配置文件4大部分介绍:

1)Profiles部分。它是默认的,这部分包含一些用于开发或测试场景的示例配置,这些配置涉及fabric目录中的加密部分。configtxgen工具允许通过-profile标签来指定配置文件。Profiles部分可以显式声明所有配置,但是通常都是从默认配置中继承。

2)Organizations部分。它是默认的,这部分包含示例配置MSP定义的单一引用。对于生产部署,应该删除这部分配置,并以新网络成员的MSP定义来替代它。组织中每一个元素都必须带有锚标签,如&orgName,这些标签可以在Profiles中部分引用。

3)默认部分。此部分是Orderer和Application的配置,包括一些属性配置,如BatchTimeout和一般用作继承的基础值。

4)Capabilities部分: 定义了存在于结构二进制文件中的功能,以便该二进制文件安全地参与结构网络. 

例如,如果添加了新的MSP类型,则较新的二进制文件可能会识别并验证此类型的签名,而没有此支持的旧二进制文件将无法验证这些事务。这可能导致具有不同世界状态的不同版本的结构二进制文件。 相反,为通道定义功能会通知那些没有此功能的二进制文件。它们必须在升级之前停止处理事务.  对于v1.0.x,如果定义了任何功能(包括关闭所有功能的配置),那么v1.0.x的peer 会主动崩溃.

 

执行流程:

  1. 生产系统文件的创世区块:

configtxgen -profile TwoOrgsOrdererGenesis -channelID systemchannel -outputBlock ./channel-artifacts/genesis.block

  1. 生产应用通道的通道文件

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID testchannel

  1. 将整个raft-example文件夹拷贝到其他四台主机上(尽量保持所有主机的全路径相同)

 

准备主机1其他配置文件:

       包括:docker-compose-ca.yaml、docker-compose-cli.yaml、docker-compose-couchdb0.yaml、docker-compose-orderer.yaml、docker-compose-peer.yaml。对应的文件内容如下:

 

docker-compose-ca.yaml

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
 
version: '2'
 
services:
  ca0:
    image: hyperledger/fabric-ca:latest
    environment:
      - FABRIC_CA_HOME=/var/hyperledger/fabric-ca-server
      - FABRIC_CA_SERVER_CA_NAME=ca-org1
      - FABRIC_CA_SERVER_CA_CERTFILE=/var/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
      - FABRIC_CA_SERVER_CA_KEYFILE=/var/hyperledger/fabric-ca-server-config/f927725bac311668c1ee983e7adff9124edaabeee35ffccaa1bbb1e02ea4e820_sk
      - FABRIC_CA_SERVER_TLS_ENABLED=true
      - FABRIC_CA_SERVER_TLS_CERTFILE=/var/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
      - FABRIC_CA_SERVER_TLS_KEYFILE=/var/hyperledger/fabric-ca-server-config/f927725bac311668c1ee983e7adff9124edaabeee35ffccaa1bbb1e02ea4e820_sk
      - FABRIC_CA_SERVER_PORT=7054
    ports:
      - "7054:7054"
    command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
    volumes:
      - ./crypto-config/peerOrganizations/org1.example.com/ca/:/var/hyperledger/fabric-ca-server-config
    container_name: ca_peerOrg1

 

docker-compose-cli.yaml

version: '2'
services:
  cli:
    container_name: cli
    image: hyperledger/fabric-tools:latest
    tty: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - FABRIC_LOGGING_SPEC=INFO
      - GODEBUG=netdns=go
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    volumes:
      - /var/run/:/host/var/run/
      - ./chaincode:/opt/gopath/src/github.com/chaincode
      - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
      - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    extra_hosts:
      - "orderer0.example.com:192.168.128.81"
      - "orderer1.example.com:192.168.128.75"
      - "orderer2.example.com:192.168.128.76"
      - "orderer3.example.com:192.168.128.77"
      - "orderer4.example.com:192.168.128.63"
      - "peer0.org1.example.com:192.168.128.81"
      - "peer1.org1.example.com:192.168.128.75"
      - "peer2.org1.example.com:192.168.128.76"
      - "peer3.org1.example.com:192.168.128.77"

 

docker-compose-couchdb0.yaml

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
 
services:
  couchdb0:
    container_name: couchdb0
    image: hyperledger/fabric-couchdb
    # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
    # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
    environment:
      - COUCHDB_USER=
      - COUCHDB_PASSWORD=
    # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
    # for example map it to utilize Fauxton User Interface in dev environments.
    ports:
      - "5984:5984"

 

docker-compose-orderer.yaml

version: '2'
volumes:
  orderer0.example.com:
services:
  orderer0.example.com:
    container_name: orderer0.example.com
    image: hyperledger/fabric-orderer:latest
    environment:
      - FABRIC_LOGGING_SPEC=INFO
      - GODEBUG=netdns=go
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      # enabled TLS
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      - ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
      - ORDERER_KAFKA_VERBOSE=true
      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/:/var/hyperledger/orderer/tls
      - orderer0.example.com:/var/hyperledger/production/orderer
    ports:
      - 7050:7050
    extra_hosts:
      - "orderer0.example.com:192.168.128.81"
      - "orderer1.example.com:192.168.128.75"
      - "orderer2.example.com:192.168.128.76"
      - "orderer3.example.com:192.168.128.77"
      - "orderer4.example.com:192.168.128.63"

 

docker-compose-peer.yaml

version: '2'
volumes:
  peer0.org1.example.com:
services:
  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    hostname: peer0.org1.example.com
    image: hyperledger/fabric-peer:latest
    environment:
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984
      # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
      # provide the credentials for ledger to connect to CouchDB.  The username and password must
      # match the username and password set for the associated CouchDB.
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      - CORE_PEER_ID=peer0.org1.example.com
      - GODEBUG=netdns=go
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - FABRIC_LOGGING_SPEC=INFO
      - 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=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    volumes:
      - /var/run/:/host/var/run/
      - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
      - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
      - peer0.org1.example.com:/var/hyperledger/production
    ports:
      - 7051:7051
      - 7052:7052
      - 7053:7053
    extra_hosts:
      - "orderer0.example.com:192.168.128.81"
      - "orderer1.example.com:192.168.128.75"
      - "orderer2.example.com:192.168.128.76"
      - "orderer3.example.com:192.168.128.77"
      - "orderer4.example.com:192.168.128.63"
      - "couchdb0:192.168.128.81"

到此,第一台主机所有配置文件准备完毕。

 

3.3 主机配置

配置文件

由于节点的配置文件类似,只要通过稍微修改即可。因此,这里把第1台主机上的节点配置文件(docker-compose-ca.yaml、docker-compose-cli.yaml、docker-compose-couchdb0.yaml、docker-compose-orderer.yaml、docker-compose-peer.yaml)拷贝到第2-5台主机上。需要注意的是第5台主机只是运行一个orderer节点,因此除了orderer和cli配置文件,其他的配置文件都可以删除。

 

配置文件适配

       2-5号主机把拷贝过来的节点配置文件的节点序号改成对应的节点序号即可,如2号主机运行1号orderer节点,则把orderer的配置文件中所有orderer0改成orderer1即可。其他文件修改方法相同。

 

3.4 其他配置

Chaincode配置

       把fabric-samples/chaincode/chaincode_example02/go目录下的chaincode_example02.go合约代码拷贝到每台主机的raft-example/chaincode目录下

域名配置

为了提高域名解析的速度从而提到节点间的交互速度,最好把各节点的域名信息配置的系统/etc/hosts文件里:

192.168.128.81 peer0.org1.example.com couchdb0 ca_peerOrg1
192.168.128.75 peer1.org1.example.com
192.168.128.76 peer2.org1.example.com
192.168.128.77 peer3.org1.example.com
192.168.128.81 orderer0.example.com
192.168.128.75 orderer1.example.com
192.168.128.76 orderer2.example.com
192.168.128.77 orderer3.example.com
192.168.128.63 orderer4.example.com

3.5 启动网络

通过命令docker-compose -f docker-compose-orderer.yaml up –d启动orderer启动,其他节点修改对应的配置文件即可;值得注意的是,每天主机都要首先启动orderer节点,而且启动完orderer节点需要等15秒后再其他节点,因为orderer在寻找其他orderer节点需要时间,具体时间因设备配置不同而不同。同样也可以看输出结果判断orderer节点是否已准备好。

       另外,也可以编写启动和停止脚本,方便测试。

例子:1号主机启动脚本

#!/bin/bash
docker-compose -f ../docker-compose-orderer.yaml up -d
sleep 30
docker-compose -f ../docker-compose-peer.yaml up -d
docker-compose -f ../docker-compose-couchdb0.yaml up -d
docker-compose -f ../docker-compose-cli.yaml up -d
docker-compose -f ../docker-compose-ca.yaml up -d

 

4、交互操作

搭建交互网络

1号主机

创建通道:

peer channel create -o orderer0.example.com:7050 -c testchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

返回结果:

 

 

在当前peer加入通道

peer channel join -b testchannel.block

 

在当前peer安装chaincode

peer chaincode install -n myccode -v 1.0 -l golang –p github.com/chaincode

 

将chaincode打包

peer chaincode package -p github.com/chaincode -n myccode -v 1.0 myccode.1.0.out

 

 

把创世块从docker容器中拷贝到宿主机目录

docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/testchannel.block ./channel-artifacts

 

把chaincode编译好的二进制文件从docker容器中拷贝到宿主机目录

docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/myccode.1.0.out ./channel-artifacts

 

把1号主机上的channel-artifacts文件夹拷贝到其他远程主机同样的目录下。

 

2号主机

进入到cli容器中

docker exec -it cli bash

把创世块文件和链码文件拷贝到docker容器中

cp ./channel-artifacts/testchannel.block /opt/gopath/src/github.com/hyperledger/fabric/peer
cp ./channel-artifacts/myccode.1.0.out /opt/gopath/src/github.com/hyperledger/fabric/peer

将当前peer加入到通道中

peer channel join -b testchannel.block

 

 

在当前peer安装chaincode

peer chaincode install myccode.1.0.out

 

其他主机

3-4号主机上执行与2台主机同样的操作,5号主机没有peer节点,所有不需要执行同样的操作。

实例化chaincode

回到第一台主机进入cli容器

实例化链码,这时会有一个docker容器去运行指定的链码

peer chaincode instantiate -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C testchannel -n myccode -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")'

 

 

交互测试

查看初始化结果

查看初始化结果是否成功

peer chaincode query -C testchannel -n myccode -c '{"Args":["query","a"]}'

 

转账

将a的20个token转给b

peer chaincode invoke -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C testchannel -n myccode --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","20"]}'

 

查询转账后的结果:

 

在其他主机上查询a和b的值,得到同样的结果。

 

5、总结

       一开始没有详细理解fabric的配置过程,只是知道官方项目中有自动搭建脚本,而本人又想理解整个fabric环境搭建过程和原来,因此在搭建过程中遇到了不少问题,最后总算完成了。同时,把现在重新整理把之前的搭建过程在此记录下来,各位可以踊跃批评。