相信很多人都碰到这种问题,这里给出一种方案,并带你分析一下为什么出现这种问题。
问题描述
话不多说,直接上干货
先来张报错的图:
错误提示为:
Error: could not assemble transaction, err proposal response was not successful, error code 500, msg error starting container: error starting container: Failed to generate platform-specific docker build: Error returned from build: 1 "chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/internal/types/types.go:13:2: cannot find package "github.com/go-openapi/spec" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/go-openapi/spec (vendor tree)
/opt/go/src/github.com/go-openapi/spec (from $GOROOT)
/chaincode/input/src/github.com/go-openapi/spec (from $GOPATH)
/opt/gopath/src/github.com/go-openapi/spec
chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/metadata/a_metadata-packr.go:7:8: cannot find package "github.com/gobuffalo/packr" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/gobuffalo/packr (vendor tree)
/opt/go/src/github.com/gobuffalo/packr (from $GOROOT)
/chaincode/input/src/github.com/gobuffalo/packr (from $GOPATH)
/opt/gopath/src/github.com/gobuffalo/packr
chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/contractapi/contract_chaincode.go:14:2: cannot find package "github.com/hyperledger/fabric-chaincode-go/pkg/cid" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-chaincode-go/pkg/cid (vendor tree)
/opt/go/src/github.com/hyperledger/fabric-chaincode-go/pkg/cid (from $GOROOT)
/chaincode/input/src/github.com/hyperledger/fabric-chaincode-go/pkg/cid (from $GOPATH)
/opt/gopath/src/github.com/hyperledger/fabric-chaincode-go/pkg/cid
chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/contractapi/contract_chaincode.go:15:2: cannot find package "github.com/hyperledger/fabric-chaincode-go/shim" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-chaincode-go/shim (vendor tree)
/opt/go/src/github.com/hyperledger/fabric-chaincode-go/shim (from $GOROOT)
/chaincode/input/src/github.com/hyperledger/fabric-chaincode-go/shim (from $GOPATH)
/opt/gopath/src/github.com/hyperledger/fabric-chaincode-go/shim
chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/contractapi/contract_chaincode.go:20:2: cannot find package "github.com/hyperledger/fabric-protos-go/peer" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-protos-go/peer (vendor tree)
/opt/go/src/github.com/hyperledger/fabric-protos-go/peer (from $GOROOT)
/chaincode/input/src/github.com/hyperledger/fabric-protos-go/peer (from $GOPATH)
/opt/gopath/src/github.com/hyperledger/fabric-protos-go/peer
chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/hyperledger/fabric-contract-api-go/internal/utils/utils.go:11:2: cannot find package "github.com/xeipuuv/gojsonschema" in any of:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/xeipuuv/gojsonschema (vendor tree)
/opt/go/src/github.com/xeipuuv/gojsonschema (from $GOROOT)
/chaincode/input/src/github.com/xeipuuv/gojsonschema (from $GOPATH)
/opt/gopath/src/github.com/xeipuuv/gojsonschema
根据图中可以看出执行 peer chaincode instantiate
命令出现错误,在前面的peer chaincode install
命令是成功的,到了实例化的时候出现问题。
其实我们可以看一下上面报错的log,可以发现是找不到对应的包
可以看到上面他们去了以下几个路径去找包:
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go/testChaincode/vendor/github.com/go-openapi/spec (vendor tree)
/opt/go/src/github.com/go-openapi/spec (from $GOROOT)
/chaincode/input/src/github.com/go-openapi/spec (from $GOPATH)
/opt/gopath/src/github.com/go-openapi/spec
现在进行一下一点验证:
1、在vendor tree
、$GOROOT
、$GOPATH
这几个路径下面是否能够找到。方法很简单,上面路径不是给出了。直接通过命令docker exec -it cli bash
进入cli容器,看看这个容器下面是否存在上述的几个路径。
2、答案肯定是不存在的,如果存在也不至于找不到。问题到这里已经很明显了,因为容器cli中没有链码运行所需要的依赖包。
3、既然没有,那我们给cli容器依赖包就好啦。
解决办法
那么怎么给cli容器依赖包呢?有以下几个方法:
1、直接在cli容器中go get所需要的依赖包。(效率最低的方式,每次重启网络都需要进入cli容器中go get一波)极其不推荐
这种方式。
2、我们看一下vendor tree
这个路径,这个路径在cli容器中不存在的。那么为什么会有这个路径呢?可能是你在链码的目录下进行过govendor
或者go mod vendor
等操作。会先去链码依赖包所在的位置,也就是vendor tree中去找。在vendor tree
中找不到,再去GOROOT
找,找不到再去GOPAHT
中找,如果都找不到,那就报找不到包的错误。解决的办法很简单,就是让cli容器的/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go
存在就好啦!那么怎么让他存在呢,就是把本地项目的链码路径挂载在这个路径下面就ok了。
现在我们只需要完成挂载这个路径到cli就好,那么如何挂载呢?首先要明白cli这个容器是根据什么启动呢?那当然是你配置的yaml
文件。
在我的容器启动配置文件中,关于cli的文件配置是这样的(此处是粘贴的我自己的,大家可以根据自己的配置文件动态调整一下):
cli:
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- SYS_CHANNEL=$SYS_CHANNEL
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#- FABRIC_LOGGING_SPEC=DEBUG
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.fabric-iot.edu: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.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/users/Admin@org1.fabric-iot.edu/msp
- GO111MODULE=on
- GOPROXY=https://goproxy.io,direct
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/yjzhu1106/fabric-single/chaincode
# - ./../../../../../../src/github.com/ethereum/go-ethereum:/opt/gopath/src/github.com/ethereum/go-ethereum
- ./../../../../../../src/:/opt/gopath/src/
# - ./../../chaincode/go/pdpc/vendor/github.com:/opt/gopath/src/github.com
- ./../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.fabric-iot.edu
- peer0.org1.fabric-iot.edu
- peer1.org1.fabric-iot.edu
- peer0.org2.fabric-iot.edu
- peer1.org2.fabric-iot.edu
networks:
- bc_net
接下来讲一下如何挂载(完成下述目标):
- 让cli容器的
/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go
存在就好啦!那么怎么让他存在呢,就是把本地项目的链码路径挂载在这个路径下面就ok了。
1、大家可以看到cli的volumes
属性,就在volumes属性下面添加一个挂在路径的配置就好。
2、可以看到,我现在挂载了6个路径,还有两个注释掉的路径。
3、本地和容器之间的挂载关系为: - 本地路径:容器的路径
。现在我本地链码所在的位置为:/root/go/src/github.com/yjzhu1106/fabric-single/chaincode/go
,我想把这个链码的位置挂载在/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go
。
- /root/go/src/github.com/yjzhu1106/fabric-single/chaincode/go:/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go
4、上面就实现了挂载,那么问题是,如果我的项目换了个电脑,本地的路径发生了改变,是不是就要再次更改挂载的路径。那么我们就用相对路径来挂载。首先呢,我的配置文件yaml
所在的位置为:/root/go/src/github.com/yjzhu1106/fabric-single/network/compose-files
,那么链码所在路径相对与配置文件的位置应该是:../chaincode/go/
,将步骤3中的更新为:
- ./../../chaincode/go:/chaincode/input/src/github.com/yjzhu1106/fabric-single/chaincode/go
5、最重要的一步,你需要重新启动你的网络,然后再安装试一下,这个问题应该是解决的。
tip:你要保证你链码的
vendor
中有所有的依赖,据我所知,依赖包的依赖,是无法下载到vendor
中的,所以再出现找不到包的问题,就去你链码的vendor
中,把缺少的依赖直接git clone
到vendor
里面就可以啦。git clone
的时候注意路径问题,该在哪个文件夹下就在哪个文件夹下。