protected ProtocolMetaData doDeploy(Archive<?> archive) throws DeploymentException {
    List<String> command = new ArrayList<>();
    command.add("gcloud");
    if (configuration.isDebug()) {
      command.add("--verbosity");
      command.add("debug");
    }
    command.add("preview");
    command.add("app");
    command.add("run");
    command.add(getAppLocation().getPath());

    log.info("GCloud command: " + command);

    try {
      DockerContainer.removeAll();
    } catch (Exception e) {
      throw new DeploymentException("Cannot remove all previous Docker containers.", e);
    }

    ProcessBuilder builder = new ProcessBuilder(command);
    builder.redirectErrorStream(true);

    try {
      process = builder.start();
    } catch (IOException e) {
      throw new IllegalStateException("Error running gcloud!", e);
    }

    Thread streamThread =
        new Thread(
            new Runnable() {
              public void run() {
                try {
                  try (InputStream ps = process.getInputStream()) {
                    int x;
                    while ((x = ps.read()) != -1) {
                      System.out.write(x);
                    }
                  }
                } catch (IOException ignored) {
                }
              }
            });
    streamThread.start();

    String host = configuration.getHost();
    int port = readPort();

    String serverUrl = "http://" + host + ":" + port + "/_ah/health";
    try {
      delayArchiveDeploy(
          serverUrl, configuration.getStartupTimeout(), 2000L, new GCloudURLChecker());
    } catch (Exception e) {
      throw new DeploymentException("Error delaying archive deployment.", e);
    }

    return getProtocolMetaData(host, port, DEFAULT);
  }
 protected int readPort() throws DeploymentException {
   int retry = 20;
   Exception e = null;
   while (retry > 0) {
     try {
       DockerContainer utils = DockerContainer.getLast();
       return utils.getPort();
     } catch (Exception ex) {
       e = ex;
     }
     try {
       Thread.sleep(1000); // wait 1sec
     } catch (InterruptedException ie) {
       Thread.currentThread().interrupt();
       throw new IllegalStateException(ie);
     }
     retry--;
   }
   throw new DeploymentException("Cannot read port.", e);
 }
 @Override
 protected void shutdownServer() {
   if (process != null) {
     try {
       process.destroy();
     } finally {
       try {
         DockerContainer.removeAll();
       } catch (Exception e) {
         log.warning("Could not cleanup Docker containers.");
       }
     }
   }
 }