SkillAgentSearch skills...

Dockerode

Docker + Node = Dockerode (Node.js module for Docker's Remote API)

Install / Use

/learn @apocas/Dockerode
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

dockerode

Not another Node.js Docker Remote API module.

dockerode objectives:

  • streams - dockerode does NOT break any stream, it passes them to you allowing for some stream voodoo.
  • stream demux - Supports optional stream demultiplexing.
  • entities - containers, images and execs are defined entities and not random static methods.
  • run - dockerode allow you to seamless run commands in a container aka docker run.
  • tests - dockerode really aims to have a good test set, allowing to follow Docker changes easily, quickly and painlessly.
  • feature-rich - There's a real effort in keeping All Docker Remote API features implemented and tested.
  • interfaces - Features callback and promise based interfaces, making everyone happy :)

Ecosystem

Installation

npm install dockerode

Usage

  • Input options are directly passed to Docker. Check Docker API documentation for more details.
  • Return values are unchanged from Docker, official Docker documentation will also apply to them.
  • Check the tests and examples folder for more examples.

Getting started

To use dockerode first you need to instantiate it:

var Docker = require('dockerode');
var docker = new Docker({socketPath: '/var/run/docker.sock'});
var docker1 = new Docker(); //defaults to above if env variables are not used
var docker2 = new Docker({host: 'http://192.168.1.10', port: 3000});
var docker3 = new Docker({protocol:'http', host: '127.0.0.1', port: 3000});
var docker4 = new Docker({host: '127.0.0.1', port: 3000}); //defaults to http

//protocol http vs https is automatically detected
var docker5 = new Docker({
  host: '192.168.1.10',
  port: process.env.DOCKER_PORT || 2375,
  ca: fs.readFileSync('ca.pem'),
  cert: fs.readFileSync('cert.pem'),
  key: fs.readFileSync('key.pem'),
  version: 'v1.25' // required when Docker >= v1.13, https://docs.docker.com/engine/api/version-history/
});

var docker6 = new Docker({
  protocol: 'https', //you can enforce a protocol
  host: '192.168.1.10',
  port: process.env.DOCKER_PORT || 2375,
  ca: fs.readFileSync('ca.pem'),
  cert: fs.readFileSync('cert.pem'),
  key: fs.readFileSync('key.pem')
});

//using a different promise library (default is the native one)
var docker7 = new Docker({
  Promise: require('bluebird')
  //...
});
//...

Manipulating a container:

// create a container entity. does not query API
var container = docker.getContainer('71501a8ab0f8');

// query API for container info
container.inspect(function (err, data) {
  console.log(data);
});

container.start(function (err, data) {
  console.log(data);
});

container.remove(function (err, data) {
  console.log(data);
});

// promises are supported
var auxContainer;
docker.createContainer({
  Image: 'ubuntu',
  AttachStdin: false,
  AttachStdout: true,
  AttachStderr: true,
  Tty: true,
  Cmd: ['/bin/bash', '-c', 'tail -f /var/log/dmesg'],
  OpenStdin: false,
  StdinOnce: false
}).then(function(container) {
  auxContainer = container;
  return auxContainer.start();
}).then(function(data) {
  return auxContainer.resize({
    h: process.stdout.rows,
    w: process.stdout.columns
  });
}).then(function(data) {
  return auxContainer.stop();
}).then(function(data) {
  return auxContainer.remove();
}).then(function(data) {
  console.log('container removed');
}).catch(function(err) {
  console.log(err);
});

You may also specify default options for each container's operations, which will always be used for the specified container and operation.

container.defaultOptions.start.Binds = ["/tmp:/tmp:rw"];

Stopping all containers on a host

docker.listContainers(function (err, containers) {
  containers.forEach(function (containerInfo) {
    docker.getContainer(containerInfo.Id).stop(cb);
  });
});

Building an Image

Context: provides the path to the Dockerfile. Additionaly files that are involved in the build must be explicitly mentioned in src array, since they are sent to a temp env to build. Example: file for COPY command are extracted from that temporary environment.

docker.buildImage('archive.tar', {t: imageName}, function (err, response){
  //...
});

docker.buildImage({
  context: __dirname,
  src: ['Dockerfile', 'file1', 'file2']
}, {t: imageName}, function (err, response) {
  //...
});

buildImage returns a Promise of NodeJS stream. In case you want to find out when the build has finished, you must follow the progress of the build with the modem instance in dockerode:

let dockerode = new Dockerode();
let stream = await dockerode.buildImage(...);
await new Promise((resolve, reject) => {
  dockerode.modem.followProgress(stream, (err, res) => err ? reject(err) : resolve(res));
});
// Build has finished

Creating a container:

docker.createContainer({Image: 'ubuntu', Cmd: ['/bin/bash'], name: 'ubuntu-test'}, function (err, container) {
  container.start(function (err, data) {
    //...
  });
});
//...

Streams goodness:

//tty:true
docker.createContainer({ /*...*/ Tty: true /*...*/ }, function(err, container) {

  /* ... */

  container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
    stream.pipe(process.stdout);
  });

  /* ... */
});

//tty:false
docker.createContainer({ /*...*/ Tty: false /*...*/ }, function(err, container) {

  /* ... */

  container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
    //dockerode may demultiplex attach streams for you :)
    container.modem.demuxStream(stream, process.stdout, process.stderr);
  });

  /* ... */
});

docker.createImage({fromImage: 'ubuntu'}, function (err, stream) {
  stream.pipe(process.stdout);
});

//...

There is also support for HTTP connection hijacking, which allows for cleaner interactions with commands that work with stdin and stdout separately.

docker.createContainer({Tty: false, /*... other options */}, function(err, container) {
  container.start(function(err) {
    container.exec({Cmd: ['shasum', '-'], AttachStdin: true, AttachStdout: true}, function(err, exec) {
      exec.start({hijack: true, stdin: true}, function(err, stream) {
        // shasum can't finish until after its stdin has been closed, telling it that it has
        // read all the bytes it needs to sum. Without a socket upgrade, there is no way to
        // close the write-side of the stream without also closing the read-side!
        fs.createReadStream('node-v5.1.0.tgz', 'binary').pipe(stream);

        // Fortunately, we have a regular TCP socket now, so when the readstream finishes and closes our
        // stream, it is still open for reading and we will still get our results :-)
        docker.modem.demuxStream(stream, process.stdout, process.stderr);
      });
    });
  });
});

Equivalent of docker run in dockerode:

  • image - container image
  • cmd - command to be executed
  • stream - stream(s) which will be used for execution output.
  • create_options - (optional) Options used for container creation. Refer to the DockerEngine ContainerCreate documentation for the possible values
  • start_options - (optional) Options used for container start. Refer to the DockerEngine ContainerStart documentation for the possible values
  • callback - callback called when execution ends (optional, promise will be returned if not used).
//callback
docker.run('ubuntu', ['bash', '-c', 'uname -a'], process.stdout, function (err, data, container) {
  console.log(data.StatusCode);
});

//promise
docker.run(testImage, ['bash', '-c', 'uname -a'], process.stdout).then(function(data) {
  var output = data[0];
  var container = data[1];
  console.log(output.StatusCode);
  return container.remove();
}).then(function(data) {
  console.log('container removed');
}).catch(function(err) {
  console.log(err);
});

or, if you want to split stdout and stderr (you must to pass Tty:false as an option for this to work)

docker.run('ubuntu', ['bash', '-c', 'uname -a'], [process.stdout, process.stderr], {Tty:false}, function (err, data, container) {
  console.log(data.StatusCode);
});

If you provide a callback, run will return an EventEmitter supporting the following events: container, stream, data. If a callback isn't provided a promise will be returned.

docker.run('ubuntu', ['bash', '-c', 'uname -a'], [process.stdout, process.stderr], {Tty:false}, function (err, data, container) {
  //...
}).on('container', function (container) {
  //...
});

And here is one more complex example using auto-remove and Docker network.

docker.run('some-python-image', ['python', 'main.py', arg], process.stdout, {name: 'my-python-container', HostConfig: { AutoRemove: true, NetworkMode: 'my_network'}}, function(err, data, container) {
  // Do stuff
});

Equivalent of docker pull in dockerode:

  • repoTag - container image name (optionally with tag) myrepo/myname:withtag
  • options - extra options passed to create image.
  • callback - callback called when execution ends.
docker.pull('myrepo/myname:tag', function (err, stream) {
  // streaming output from pull...
});

Pull from private repos

docker-modem already base64 encodes the necessary auth object for you.

var auth = {
  username: 'username',
View on GitHub
GitHub Stars4.9k
CategoryDevelopment
Updated5h ago
Forks486

Languages

JavaScript

Security Score

100/100

Audited on Apr 1, 2026

No findings