Home > Software design >  Java docker execute get stdin
Java docker execute get stdin

Time:10-21

Hello to all I am using java to create docker containers, I have a problem. Once the container is created I would like to interact with it via stdin but I haven't found a way to do it via SDK java (I use this https://github.com/docker-java/docker-java). I found a code that hijacks the HTTP call to be able to send the commands, but the problem with this code is that it can only send the commands 1 time when it closes the output stream. The code used for the hijack is this here:

https://gist.github.com/missedone/76517e618486db746056

Classse HttpHijack: as you can see on line 120 it closes the stream: socket.shutdownOutput(); (without it would not send the command)

Here is a code example:

ExecCreateCmdResponse execCreateResp = dockerClient.execCreateCmd(CONTAINER_NAME).withCmd("bash")
                .withAttachStderr(true).withAttachStdout(true).withAttachStdin(true).withTty(false).exec();

        HashMap<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");

        HttpHijack ws = new HttpHijack(new URI("http://127.0.0.1:2375/exec/"   execCreateResp.getId()   "/start"));
        String payload = "{\"Detach\": false,\"Tty\": true}";
        ws.post(headers, payload);

        String response = IOUtils.toString(send(ws, "ls -alth"), StandardCharsets.UTF_8);
        System.out.println(response);
        Thread.sleep(3000);
        response = IOUtils.toString(send(ws, "ls -alth /"), StandardCharsets.UTF_8);
        System.out.println(response);

The first call works but the second doesn't.

Can anyone help me? Is there perhaps a way to interact with the stdin directly from the SDK? Or change the HttpHijack class so that it doesn't close the stream?

I would like to be able to interact with the container bash via the exec command.

I am open to different solutions or even to the use of SDKs of verses. Thank you, and I apologize if I may not have formatted the question well, I am new here. Thanks

CodePudding user response:

I found the solution to my question.

Using this code

try (PipedOutputStream out = new PipedOutputStream();
                PipedInputStream in = new PipedInputStream(out);
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
            AttachContainerCmd attachContainerCmd = docker.attachContainerCmd(createContainerResponse.getId()).withStdIn(in)
                    .withStdOut(true).withStdErr(true).withFollowStream(true);
            attachContainerCmd.exec(new AttachContainerResultCallback());

            String line = "Hello World!";
            while (!"q".equals(line)) {
                writer.write(line   "\n");

                writer.flush();

                line = reader.readLine();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

taken from this link: https://github.com/docker-java/docker-java/issues/941#issuecomment-346377948

now i am able to get l stdin and be able to interact with both docker attach and exec. Having stdin and stdout I can redirect these streams via websocket and then be able to connect to xterm.js which was my main target.

Thanks everyone for the answers

CodePudding user response:

AFAIK docker will capture an enclosed process' stdout as log data. So what your java application that creates a container using docker run... will get is the container ID. Per design this is very suitable for server side processes that do not go interactive.

If you need something else it is questionable whether docker is the ideal solution.

  • Related