@Override
 public void execute(AbstractBuild<?, ?> build) throws DockerException {
   LOGGER.info("Stopping container " + containerId);
   DockerClient client = getClient(build);
   client.container(containerId).stop();
   getLaunchAction(build).stopped(client, containerId);
 }
  @Override
  public boolean perform(
      final AbstractBuild build, final Launcher launcher, final BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("Docker Build");

    FilePath fpChild = new FilePath(build.getWorkspace(), dockerFileDirectory);

    final String tagToUse = getTag(build, launcher, listener);
    final String url = getUrl(build);
    // Marshal the builder across the wire.
    DockerClient client = getDockerClient(build);
    final DockerClient.Builder builder = DockerClient.builder().fromClient(client);

    BuildCommandResponse response =
        fpChild.act(
            new FilePath.FileCallable<BuildCommandResponse>() {
              public BuildCommandResponse invoke(File f, VirtualChannel channel)
                  throws IOException, InterruptedException {
                try {
                  listener
                      .getLogger()
                      .println(
                          "Docker Build : build with tag "
                              + tagToUse
                              + " at path "
                              + f.getAbsolutePath());
                  DockerClient client = builder.readTimeout(3600000).build();

                  File dockerFile;

                  // Be lenient and allow the user to just specify the path.
                  if (f.isFile()) dockerFile = f;
                  else dockerFile = new File(f, "Dockerfile");

                  return client.createBuildCommand().dockerFile(dockerFile).tag(tagToUse).execute();

                } catch (DockerException e) {
                  throw Throwables.propagate(e);
                }
              }
            });

    listener.getLogger().println("Docker Build Response : " + response);

    Optional<String> id = response.imageId();
    if (!id.isPresent()) return false;

    build.addAction(
        new DockerBuildImageAction(
            url, id.get(), tagToUse, cleanupWithJenkinsJobDelete, pushOnSuccess));
    build.save();

    if (pushOnSuccess) {

      listener.getLogger().println("Pushing " + tagToUse);
      if (!tagToUse.toLowerCase().equals(tagToUse)) {
        listener
            .getLogger()
            .println(
                "ERROR: Docker will refuse to push tag name "
                    + tagToUse
                    + " because it uses upper case.");
      }

      Identifier identifier = Identifier.fromCompoundString(tagToUse);

      String repositoryName = identifier.repository.name;

      PushCommandResponse pushResponse = client.createPushCommand().name(repositoryName).execute();

      listener.getLogger().println("Docker Push Response : " + pushResponse);
    }

    if (cleanImages) {

      // For some reason, docker delete doesn't delete all tagged
      // versions, despite force = true.
      // So, do it multiple times (protect against infinite looping).
      listener.getLogger().println("Cleaning local images");

      int delete = 100;
      while (delete != 0) {
        int count = client.image(id.get()).removeCommand().force(true).execute().size();
        if (count == 0) delete = 0;
        else delete--;
      }
    }

    listener.getLogger().println("Docker Build Done");

    return true;
  }