code: func launchChaincode(ccParams *chaincodeParams, tlsPath string, done chan struct{}) {
  	const (
  		relaunchWaitTime = time.Second
  	)
  
  	for {
  		logDebugf("Starting chaincode [%s, %s]", ccParams.chaincodeBinary(), ccParams.ccID)
  		cmd := createChaincodeCmd(ccParams, tlsPath)
  
  		cmdDone := make(chan struct{})
  
  		go func() {
  			defer close(cmdDone)
  
  			err := cmd.Run()
  			if v, ok := err.(*exec.ExitError); ok {
  				logWarningf("Chaincode had an exit error - will relaunch [%s, %s]", ccParams.ccID, v)
  			} else {
  				logFatalf("Chaincode had a non-exit error [%s, %s]", ccParams.ccID, err)
  			}
  		}()
  
  		select {
  		case <-done:
  			logDebugf("Stopping chaincode [%s, %s, %d]", ccParams.chaincodeBinary(), ccParams.ccID, cmd.Process.Pid)
  			err := cmd.Process.Kill()
  			if err != nil {
  				logWarningf("Killing process failed [%s, %s]", ccParams.ccID, err)
  			}
  			return
  		case <-cmdDone:
  			time.Sleep(relaunchWaitTime)
  		}
  	}
  }
docs: // chaincoded is currently able to intercept the docker calls without need for forwarding.
  // (so reverse proxy to docker via socat is currently disabled).
  //
  //func createDockerReverseProxy() *httputil.ReverseProxy {
  //	const (
  //		defaultDockerHost = "http://localhost:2375"
  //	)
  //
  //	docker_host, ok := os.LookupEnv("DOCKER_HOST")
  //	if !ok {
  //		docker_host = defaultDockerHost
  //	}
  //
  //	url, err := url.Parse(docker_host)
  //	if err != nil {
  //		logFatalf("invalid URL for docker host: %s", err)
  //	}
  //
  //	return httputil.NewSingleHostReverseProxy(url)
  //}