apocas / dockerode

Docker + Node = Dockerode (Node.js module for Docker's Remote API)
Apache License 2.0
4.37k stars 463 forks source link

Docker run and capture output #332

Closed 3goats closed 7 years ago

3goats commented 7 years ago

Hi,

Is there a way to use docker.run and capture the output to a variable.

This is what I have so far:

var options = { Binds: ['/scans:/scans:rw'], NetworkMode:'mynet'}

docker.run('scanafi-reporting', ["python", "process.py", "test", "test", "1.5.6", "23 June 2018"], process.stdout,
    options,
    function (err, data, container) {
        console.log(data.StatusCode);
        console.log(container)

    });
aroach commented 7 years ago

I've had success with capturing the stream this way:

    var Writable = require('stream').Writable;
    // snip
    var myStream = new Writable();

    myStream._write = function write(doc, encoding, callback) {
      var StringDecoder = require('string_decoder').StringDecoder;
      var decoder = new StringDecoder('utf8');
      var result = decoder.write(doc);
      resolve(result);  // Note I'm wrapping this in a promise
    };

    // snip
    docker.run('myContainer', ['node', 'app.js'], myStream, {}...

However, I'm finding a limitation on the length of what can be outputted. It seems to cap at 8192 bytes for some reason, so if anyone has a pointer there, I'd appreciate it!

Update: I figured it out...I wasn't implementing the write function correctly and not calling the callback (next() in the sample below), therefore it would stop streaming after the first chunk.

    var myStream = new Writable();
    var output = ''

    myStream._write = function write(doc, encoding, next) {
      var StringDecoder = require('string_decoder').StringDecoder;
      var decoder = new StringDecoder('utf8');
      var result = decoder.write(doc);
      output += result;
      next()
      // resolve(result);  // Moved the resolve to the handler, which fires at the end of the stream
    };

    function handler(error, data, container) {
      if (error) {
        console.log({ 'status': 'error', 'message': error });
        reject(error)
      }
      resolve(output);
    };

    docker.run('myContainer', ['node', 'function.js'], myStream, {}, handler);
moredure commented 7 years ago

The best approach is to use library such as memory-streams to deal with output.

apocas commented 7 years ago

https://github.com/apocas/dockerode/issues/401