Sending input using STDIN

851 views
Skip to first unread message

Tim Dudgeon

unread,
Jan 11, 2017, 9:05:12 AM1/11/17
to docker-java-dev
I'm needing to using docker-java to send input to a container using STDIN (and get output from STDOUT).
I found this example:
and tried to get something working based on the execStartAttachStdin() test.
But for me its not working.

package org.squonk.execution.docker;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.ExecStartResultCallback;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

public class DockerStdin {

public static void main(String[] args) throws Exception {
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder() .build();
DockerClient dockerClient = DockerClientBuilder.getInstance(config).build();
CreateContainerResponse container = dockerClient.createContainerCmd("busybox")
.withCmd("sleep", "99")
.exec();
System.out.println("Created container " + container.getId());
InputStream stdin = new ByteArrayInputStream("STDIN\n".getBytes("UTF-8"));
ByteArrayOutputStream stdout = new ByteArrayOutputStream();

dockerClient.startContainerCmd(container.getId()).exec();

ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId())
.withAttachStdout(true)
.withAttachStdin(true)
.withCmd("cat")
.exec();

boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId())
.withDetach(false)
.withTty(true)
.withStdIn(stdin)
.exec(new ExecStartResultCallback(stdout, System.err))
.awaitCompletion(5, TimeUnit.SECONDS);

System.out.println("Completed = " + completed);
System.out.println("output = " + stdout.toString("UTF-8"));
}
}

completed is false and there is no output. I hope I reproduced the key parts of the test correctly.
Any pointers to what is wrong?
This is with docker-java 3.0.6 and docker 1.12.5.

And actually what I want to do is to pass STDIN into the container during the run command and grab the STDOUT as it executes.
Something approximating to:

echo 'Hello World!' | docker run --rm -i busybox cat > result.txt

How should I go about achieving this?

Thanks
Tim


Kanstantsin Shautsou

unread,
Jan 17, 2017, 7:38:18 PM1/17/17
to docker-java-dev
Please follow test classes to get examples. 

Tim Dudgeon

unread,
Jan 18, 2017, 4:05:24 AM1/18/17
to docker-java-dev
That's exactly what I tried to do. As I stated, the example is taken almost exactly from one of the test cases. It's as close as I could get to a standalone example of the execStartAttachStdin() test in:

marcuslinke

unread,
Jan 18, 2017, 4:37:23 AM1/18/17
to docker-java-dev
Hi Tim,

the passing of STDIN to the container is only supported by the (currently experimental) netty implementation. See https://github.com/docker-java/docker-java/wiki#intialize-docker-client-advanced to get an idea how to use
the NettyDockerCmdExecFactory. Hope that helps.

Regards

Marcus

Tim Dudgeon

unread,
Jan 19, 2017, 4:27:23 AM1/19/17
to docker-java-dev
Thank you. Using Netty was the missing bit.
How experimental is the Netty impl at present? Is it expected to replace the Jersey impl, or just be an alternative?
Tim

marcuslinke

unread,
Jan 19, 2017, 4:38:31 AM1/19/17
to docker-java-dev
The netty implementation should have replaced the jersey one already but is currently stuck because of missing netty support of unix domain sockets on macos. There is a pending PR about it: https://github.com/netty/netty/pull/6000. Beside this the netty impl is tested and ready to use.

Cheers

shengb...@gmail.com

unread,
Mar 7, 2017, 10:15:39 PM3/7/17
to docker-java-dev
Hello,I am also faced with the same question with you,I also use the example posted in https://github.com/docker-java/docker-java/blob/master/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java like you.I also implement the netty implementation.But I can't get the result when I send the stdin data to the running container ,such as "ls" command.Could you succeed as last?

shengb...@gmail.com

unread,
Mar 8, 2017, 3:02:48 AM3/8/17
to docker-java-dev
Hello,I am now wanting to sending stdin data to a running container.My code is like:
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
  .withDockerHost("tcp://docker.somewhere.tld:2376")
  .withDockerTlsVerify(true)
  .withDockerCertPath("/home/user/.docker")
  .build();

// using jaxrs/jersey implementation here (netty impl is also available)
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
  .withReadTimeout(1000)
  .withConnectTimeout(1000)
  .withMaxTotalConnections(100)
  .withMaxPerRouteConnections(10);

DockerClient dockerClient = DockerClientBuilder.getInstance(config)
  .withDockerCmdExecFactory(dockerCmdExecFactory)
  .build();
InputStream stdin = new ByteArrayInputStream("ls\n".getBytes("UTF-8"));

ByteArrayOutputStream stdout = new ByteArrayOutputStream();

ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId())
.withAttachStdout(true)
.withAttachStdin(true)
.withCmd("/bin/bash")
.exec();

boolean completed = dockerClient.execStartCmd(execCreateCmdResponse.getId())
.withDetach(false)
.withTty(true)
.withStdIn(stdin)
.exec(new ExecStartResultCallback(stdout, System.err))
 .awaitCompletion(5, TimeUnit.SECONDS);
But I couldn't get nothing although I have sent the stdin data to the running container.Could you tell me why?
Besides,when I follow the test posted in https://github.com/docker-java/docker-java/blob/master/src/test/java/com/github/dockerjava/netty/exec/ExecStartCmdExecTest.java
I don't know the idea of the config in method.such as withTty and so on.Could you send me a doc about how to use the method or how to config the method.Thanks.



marcuslinke

unread,
Mar 8, 2017, 3:05:39 AM3/8/17
to docker-java-dev
As stated in the comment

// using jaxrs/jersey implementation here (netty impl is also available)
you have to use the netty impl there like this:
DockerCmdExecFactory dockerCmdExecFactory = new NettyDockerCmdExecFactory()

 Cheers

marcuslinke

unread,
Mar 8, 2017, 7:40:28 AM3/8/17
to docker-java-dev
To keep the STDIN input stream open until the container dies you have to provide your own InputStream implementation that doesn't signal EOF via its read() method. See https://github.com/docker-java/docker-java/blob/master/src/main/java/com/github/dockerjava/netty/InvocationBuilder.java#L320 where channel.shutdownOutput() is called if the read() method returns -1. So your custom InputStream wrapper should return 0 in case the stream is empty.

Regards

marcuslinke

unread,
Mar 8, 2017, 7:53:11 AM3/8/17
to docker-java-dev
One example of such a stream implementation is System.in. It doesn't signal EOF, so  simply use System.in as stdin to the container and type some commands at the java console then.
Reply all
Reply to author
Forward
0 new messages