现在用于创建创世块和通道的依赖文件genesis.block和channel.tx已经创建完成。下一步就是要利用从网络仓库中拉取下来的镜像启动容器。
目前我的网络中有:
总计七个节点需要启动。如果此时我们docker命令依次启动这些容器,网络是无法正常工作的。每个节点所在的容器都需要进行一系列的配置,所以我将在docker-compose的配置文件中做好相应的配置,并以此文件来管理这七个节点。
有关docker-compose的知识可以通过我前面帖子《Michael.W谈Docker 第六期-docker-compose的编写》进行了解。
这个docker-compose配置文件,我还是去修改官方测试网络中的docker-compose配置文件。该文件所在路径为:hyperledger-fabric/fabric-samples/first-network/docker-compose-cli.yaml
注:以上路径为搭建hyperledger Fabric环境时创建的,如果有疑问可去我前面帖子《Michael.W谈hyperledger Fabric第一期-环境搭建》中的第6部分去查看。
将该文件拷贝到生成证书文件夹的同级目录:
$ cp /home/michael.w/hyperledger-fabric/fabric-samples/first-network/docker-compose-cli.yaml ~/test/
打开复制后的docker-compose-cli.yaml文件,我们来粗略地看看这个官方给出的测试网络的配置文件里面都做了什么:
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2' # 版本号,不需要修改
volumes: # 一下为数据卷挂载。从语法上看,这跟我在前面帖子中所讲的不太一样。这是docker-compose中的一种特殊的数据卷挂载格式,大家这里先有个印象。在后面的帖子中我会有讲解。
orderer.example.com:
peer0.org1.example.com:
peer1.org1.example.com:
peer0.org2.example.com:
peer1.org2.example.com:
# 这里可以先忽略掉上面的数据卷挂载,甚至删除掉都可以。
networks: # 声明该网络
byfn:
services: # 服务。 其中每个服务都对应一个docker容器。
orderer.example.com: # 第一个服务名(orderer节点),可自定义。官方给出的配置文件是用orderer节点的域名来做服务名,也可以改成其他字符串来代替。
extends: # 表名该服务是继承于base/docker-compose-base.yaml文件中的orderer.example.com服务。
file: base/docker-compose-base.yaml
service: orderer.example.com # 继承于的服务名
container_name: orderer.example.com # 自定义orderer节点容器的容器名
networks: # 该容器所处的网络
- byfn # 前面已声明过byfn网络
peer0.org1.example.com: # 第二个服务名(peer组织1的peer0节点),可自定义
# 下面这些与上面orderer节点的一样,不再赘述
container_name: peer0.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org1.example.com
networks:
- byfn
peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org1.example.com
networks:
- byfn
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org2.example.com
networks:
- byfn
peer1.org2.example.com:
container_name: peer1.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org2.example.com
networks:
- byfn
cli: # 客户端节点
# 这下面的配置信息我先不一一解释,等后面修改到这了我在说
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_LOGGING_LEVEL=INFO
- 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/[email protected]/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
networks:
- byfn
首先,orderer节点和peer组织的众多节点都继承了base/docker-compose-base.yaml配置文件,所以需要去原来的测试网络的目录中将里面的base目录复制过,而且要跟该docker-compose-cli.yaml处于同级目录:
$ cp -r /home/michael.w/hyperledger-fabric/fabric-samples/first-network/base ~/test
其次,我的网络里有两个peer组织,那么就需要两个客户端。上面的配置文件里只有一个客户端服务,这样可以么?后面我会通过特殊的手段来解决这个问题,不要急。
由于配置文件中的orderer节点服务和peer节点服务都继承于其他文件,修改起来比较繁琐,后面再讲。所以,先来看一下docker-compose配置文件中有关客户端的配置:
cli: # 客户端节点
container_name: cli # 启动后客户端容器名
image: hyperledger/fabric-tools:$IMAGE_TAG # 客户端容器依赖的镜像名
# 利用docker images命令可以查看本地是否有hyperledger/fabric-tools这个镜像。如果前面都按照我帖子中的步骤走的话,本地是有这个镜像的。
# $IMAGE_TAG是外部引入的环境变量,表示版本tag。经过查询[1],该变量值为latest。
tty: true # 是否与一个终端绑定。用于人机交互。
stdin_open: true # 是否对标准输入开放。用于人机交互。
environment: # 当客户端容器启动起来后其内部的环境变量
- GOPATH=/opt/gopath # 容器的GOPATH,官方制作镜像时就是这样设定的,不需要改
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # 本地套接字文件,用于进程间通信,不需要修改。
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_LOGGING_LEVEL=INFO # 日志等级[2]
- CORE_PEER_ID=cli # 当前客户端节点的ID(名字),自定义
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # 客户端启动后会根据这个配置自动连接到某个peer节点上。这里设置的是要连接的peer节点的地址+端口。
- CORE_PEER_LOCALMSPID=Org1MSP # 客户端连接的peer节点属于的组织ID(去configtx.yaml文件中查)
- CORE_PEER_TLS_ENABLED=true # 客户端在进行数据通信的时候是否加密(TLS加密,即https协议中的s所指)
# 如果说CORE_PEER_TLS_ENABLED的值被设置为true,下面三个环境变量配置才生效![3]
- 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
# 通信的时候使用的TSL证书(使用客户端连接到的peer节点的TSL证书)。
#由下面volumes数据卷挂载的信息可知:我在宿主机生成的证书文件的路径被挂载到该容器的/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto路径下
# 所以我直接将我宿主机中找到客户端连接到的peer节点下的对应证书文件的相对路径,然后拼贴到/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto路径后即可!
- 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
# 通信的时候使用的TSL私钥(使用客户端连接到的peer节点的TSL私钥)。
- 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
# 通信的时候使用的TSL根证书(使用客户端连接到的peer节点的TSL根证书)。根证书就是由拥有最高签发等级的签发机构所发行的证书。
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
# 这是一个非常重要的环境变量。因为该客户端想要连接网络必须有一个用户的身份[4]。假设客户端启动后要连接到组织1中的peer节点peer0,那以什么身份去连接呢?要以组织A下的user节点的身份去连接。
# 这里就是从该组织下的users路径下选择一个user节点的msp路径,来设置该客户端的访问身份。
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # 当使用者进入容器后所处于的进程路径。相当于cd到这个路径下。
command: /bin/bash # 容器启动后默认执行的第一条语句。
volumes: # 该容器进行的数据卷挂载
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode # 宿主机存放链码的目录挂载到该容器的对应路径上
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ # 宿主机存放证书的目录挂载到该容器的对应路径上
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
# 一般开发者会把一些在容器启动后需要执行的相关脚本文件存放到宿主机的scripts目录下,这里就是将该目录挂载到容器上。暂时还不需要这个。
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
# 一般我将前面生成的创世区块文件、通道文件、更新锚节点文件都放在这个channel-artifacts目录下[5]。这里是将该文件路径挂载到容器
depends_on: # 该容器的依赖项,决定容器之间的启动顺序。
# 关于以下选项具体表示什么,在后面的帖子中会讲到。
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
networks: # 该容器处于的网络
- byfn
[1] 关于外部引入的环境变量$IMAGE_TAG的查询:
利用指令来查询一下first-network中关于IMAGE_TAG的相关信息:
$ grep -r "IMAGE_TAG" /home/michael.w/hyperledger-fabric/fabric-samples/first-network
可见IMAGE_TAG变量已经在一个叫.env的文件中定义了。所以在我们修改这个文件时,要么把这个变量去掉,要么把这个变量改为latest。
[2] 日志的等级一共分为6档,等级从高到低排序:
打日志的数据量:critical
[3] 任何一个peer节点或user节点(客户端)的证书文件路径下面都有一个msp目录和tls目录。msp目录保存着该peer节点的身份信息(也可以理解为账户信息),tls目录保存着利用该节点进行TLS加密所需的秘钥和证书。
注:以_sk和.key结尾的文件为秘钥文件,以.pem和.crt结尾的为证书文件。
[4] 一个peer组织中的user种类可分为两类:管理员(Admin)和普通用户(User)。普通用户只能做交易(写账本操作)和查询(读账本)操作,而管理员除了交易和查询外还可以做创建通道、让某个节点加入通道、安装链码和初始化链码等操作。
[5] 创建一个channel-artifacts文件夹,将之前生成的创世区块、通道和更新锚节点文件转移到里面。
$ mkdir channel-artifacts
$ mv genesis.block org1Anchor.tx org2Anchor.tx channel.tx channel-artifacts/
我修改后的客户端部分配置文件:
cli:
container_name: cli
image: hyperledger/fabric-tools # 将变量IMAGE_TAG去掉
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.michael.com:7051 # 改为我自己网络的组织1中peer0节点的地址
- CORE_PEER_LOCALMSPID=Org1MSP # 组织1的ID
- CORE_PEER_TLS_ENABLED=true
# 一下所有环境变量皆改为对应我创建的网络的对应组件路径
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.michael.com/peers/peer0.org1.michael.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.michael.com/peers/peer0.org1.michael.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.michael.com/peers/peer0.org1.michael.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.michael.com/users/[email protected]/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./chaincode/:/opt/gopath/src/github.com/chaincode
# 将宿主机的chaincode文件夹向下移动一级,便于管理
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on: # 改为本网络的对应节点地址
- orderer.michael.com
- peer0.org1.michael.com
- peer1.org1.michael.com
- peer0.org2.michael.com
- peer1.org2.michael.com
networks:
- byfn
ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
如果需要转发,麻烦注明作者。十分感谢!
公众号名称:后现代泼痞浪漫主义奠基人