How can I execute a command against a running container?

2,042 views
Skip to first unread message

Chris Farmer

unread,
Mar 28, 2016, 12:39:03 AM3/28/16
to docker-java-dev

I posted this to stack overflow before finding this group, so this is largely duplicated there.

I have a running container and I want to execute a command against that container and get the stdout. I wanted to test this with a simple ls command, to mimic the behavior of "docker exec -it my_container_name ls" on the command line.  I have this code, and it throws at the end when I am trying to execute the command. What's the correct way to execute a command against a container that's already running?

String containerName = "my_container_name";
CreateContainerResponse container = client.createContainerCmd("busybox")
        .withImage("ubuntu")
        .withCmd("sleep", "9999")
        .withName(containerName)
        .exec();
client.startContainerCmd(container.getId()).exec();
// the container with my_container_name is now running on the docker host

ExecCreateCmdResponse execCreateCmdResponse = client.execCreateCmd(container.getId())
        .withAttachStdout(true)
        .withAttachStderr(true)
        .withCmd("ls").exec();
// exception occurs when running the following:
client.execStartCmd(execCreateCmdResponse.getId()).exec(
        new ExecStartResultCallback(System.out, System.err)).awaitCompletion();  

The stack trace is:

Exception in thread "main" com.github.dockerjava.api.exception.InternalServerErrorException: EOF

at com.github.dockerjava.jaxrs.filter.ResponseStatusExceptionFilter.filter(ResponseStatusExceptionFilter.java:53)
at org.glassfish.jersey.client.ClientFilteringStages$ResponseFilterStage.apply(ClientFilteringStages.java:134)
at org.glassfish.jersey.client.ClientFilteringStages$ResponseFilterStage.apply(ClientFilteringStages.java:123)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:171)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:251)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:683)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:679)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:435)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:338)
at com.github.dockerjava.jaxrs.async.POSTCallbackNotifier.response(POSTCallbackNotifier.java:29)
at com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier.call(AbstractCallbackNotifier.java:45)
at com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier.call(AbstractCallbackNotifier.java:22)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)




marcuslinke

unread,
Mar 29, 2016, 2:10:58 AM3/29/16
to docker-java-dev
Please use netty implementation of 'DockerCmdExecFactory' when using exec functionality. It has some improvements compared with the default jersey impl. See https://github.com/docker-java/docker-java/wiki#intialize-docker-client-advanced to get an idea how to configure it. Additionally check whether your docker deamon version matches with docker-java version as described here: https://github.com/docker-java/docker-java#docker-java-maven-dependencies.

Cheers

Chris Farmer

unread,
Mar 29, 2016, 9:09:36 AM3/29/16
to docker-java-dev
Ah, perfect.  Thanks so much for the netty suggestion!  Using the com.github.dockerjava.netty.DockerCmdExecFactoryImpl factory worked well.




Chris Farmer

unread,
Mar 29, 2016, 11:26:27 PM3/29/16
to docker-java-dev
I see that with my version of the docker-java code from mid-January, the awaitCompletion() method seems to wait forever rather than completing when the command is done.  I got a new copy of the code and built it today, and now I can successfully use this code (also without using the netty implementation of the factory)...


DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder()
.withDockerHost("tcp://my.docker.host.com:2375")
.withDockerCertPath("/my/cert/path")
.withDockerTlsVerify(false)
.build();
DockerClient client = DockerClientBuilder.getInstance(config).build();
        CreateContainerResponse containerResp = client.createContainerCmd("busybox")
        .withImage("ubuntu")
         .withCmd("sleep", "9999")
        .withAttachStderr(true)
        .withAttachStdout(true)
        .exec();
        String containerId = containerResp.getId();
        client.startContainerCmd(containerId).exec();
        
        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
        
        ExecCreateCmdResponse execCreateCmdResponse = client.execCreateCmd(containerId)
        .withAttachStdout(true)
        .withAttachStderr(true)
        .withCmd("ping", "8.8.8.8", "-c", "30")
        .exec();
        client.execStartCmd(execCreateCmdResponse.getId()).exec(
                new ExecStartResultCallback(stdout, stderr)).awaitCompletion();


Now the awaitCompletion waits just until my pings are done and it all seems happy.

Thanks again for your help.


Reply all
Reply to author
Forward
0 new messages