Accessing the output of a command running in a docker container

691 Views Asked by At

I'm trying to upgrade from docker-java 0.10.3 to 3.2.7. This line has me completely stumped:

InputStream response = 
  dockerClient.attachContainerCmd(container.getId())
    .withLogs(true)
    .withStdErr(true)
    .withStdOut(true)
    .withFollowStream(true)
    .exec();

I have managed to get round one error by changing it to

InputStream response = 
  dockerClient.attachContainerCmd(container.getId())
    .withLogs(true)
    .withStdErr(true)
    .withStdOut(true)
    .withFollowStream(true)
    .exec(new AttachContainerResultCallback());

(but my IDE says that AttachContainerResultCallback is deprecated.) The problem is that .exec() used to return an InputStream. Now it returns a void. I need the InputStream, because the output of the commands running in the container needs to find it's way to the screen. This needs to be realtime, because the user needs to see the output of the commands as they are running; I can't just copy a file at the end.

How can I get hold of this InputStream?


The error is:

java: incompatible types: inference variable T has incompatible bounds
    lower bounds: java.io.InputStream,com.github.dockerjava.api.async.ResultCallback<com.github.dockerjava.api.model.Frame>
    lower bounds: com.github.dockerjava.core.command.AttachContainerResultCallback
1

There are 1 best solutions below

0
Sergey Kochkin On

Try it:

    var outputStream = new PipedOutputStream();
    var inputStream = new PipedInputStream(outputStream);

    var response =
            dockerClient.attachContainerCmd(container.getId())
                    .withLogs(false)
                    .withStdErr(true)
                    .withStdOut(true)
                    .withFollowStream(true)
                    .exec(new ResultCallback.Adapter<>() {
                        @Override
                        public void onNext(Frame object) {
                            System.out.println(object);  //for example
                            try {
                                outputStream.write(object.getPayload());
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    });

    try {
        response.awaitCompletion();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

Variable inputStream will be what you are looking for. P.S. In my case I do withLogs(false) because it blocks the current output and I get only part of the log. It probably has something to do with the container I'm connecting to.