1

When running a

http://127.0.0.1:2375/exec/xxxxx/start

i get a response of type application/vnd.docker.raw-stream with some binary chars in the response. so for example, when calling "date" inside a docker container, the response always looks like this (screenshot made from postman):

enter image description here

in joe (editor) I see: A@@@@@@]Wed Dec 29 00:55:05 CET 2021
and vi (editor) shows A^@^@^@^@^@^@^]Wed Dec 29 00:55:05 CET 2021

I wasn´t able to find anything to control the output via docker. So I want to ask, what is the best way to get rid of these binary characters? In the end, I want to parse the result via PHP, but maybe there is a way to avoid these characters in the first place because these characters are nearly everywhere.

michabbb
  • 880
  • 2
  • 7
  • 27
  • because the result is a binary stream, i guess it´s not possible to change the way how the docker engine returns results here. but to remove the binary characters from the result, a simple preg_replace works: https://stackoverflow.com/a/8171868/1092858 – michabbb Dec 29 '21 at 01:04
  • Being able to connect to `http://localhost:2375` at all is an incredibly dangerous configuration: anyone who can connect to the Docker daemon can pretty trivially root the host, and you should reset whatever Docker daemon configuration made this available. I'd recommend trying to avoid scripting `docker exec` entirely if possible, but if it's really required, consider using a [Docker SDK](https://docs.docker.com/engine/api/sdk/) that knows how to talk to the normal container socket. – David Maze Dec 29 '21 at 12:01
  • it´s not dangerous and especially not "incredibly" dangerous, comments like these are so annoying. there´s a very good reason why docker has an API and there are tons of reasons why it makes "so much sense" talking with a docker daemon via TCP. everything is "incredible" dangerous if you don´t control who is able to talk with whom - that´s the nature of the modern technique. but saying something is dangerous "in general" - that´s naive, sorry. but I thank you for the notice about the SDK, will look into it. – michabbb Dec 29 '21 at 18:52
  • _Any process running on the same host_ can run `DOCKER_HOST=tcp://localhost:2375 docker run -v/:/host busybox vi /etc/sudoers` and give itself root. If the Docker socket is network-accessible, that expands to anyone who can reach the system over the network. "Effectively disables your root password" is very dangerous by most measures. – David Maze Dec 29 '21 at 22:32

1 Answers1

0

First:

As far as I have seen, there is no way to tell the Docker Engine to get something else than a "stream" as a response, because it´s the nature of some Docker calls, for example, if you "attach" to a running container, the output can be endless so it´s not a "one call->wait 2 seconds->get response" - because containers can run forever, so the output can be endless long.

Secondly:

Removing the binary string with a simple regex is working like explained here.

Finally:

How to read the Stream with PHP?

Using Guzzle is in most cases the easiest way to handle HTTP calls with PHP.

<?php
$response = $client->request('POST', '/exec/' . $id . '/start', [
    'json' => [
        "Detach" => false,
        "Tty"    => false,
    ],
    'stream' => true // <---------- THIS IS THE IMPORTANT PART HERE
]);

The Docker Engine Documentation clearly explains how to read the Stream:

The simplest way to implement this protocol is the following:

  1. Read 8 bytes.
  2. Choose stdout or stderr depending on the first byte.
  3. Extract the frame size from the last four bytes.
  4. Read the extracted size and output it on the correct output.
  5. Goto 1.

So with the Help of an old PHP Package, that shows how it's done, I was able to finally get a "clear" output:

$body = $response->getBody();

$str = '';
do {
    $strToUnpack = $body->read(8);
    if (strlen($strToUnpack)) {
        $decoded = \unpack('C1type/C3/N1size', $strToUnpack);
        if ($decoded) {
            $str = $body->read($decoded['size']);
            echo $str . "\n";
        }
    }
} while (!$body->of());
michabbb
  • 880
  • 2
  • 7
  • 27