diff --git a/README.md b/README.md index 83e9e14..615af86 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Not another Node.js Docker.io Remote API module. Why `dockerode` is different from other Docker node.js modules: * **streams** - `dockerode` does NOT break any stream, it passes them to you allowing for some stream voodoo. -* **stream demux** - Supports optional demultiplexing of the new attach stream system implemented in Remote API v1.6. +* **stream demux** - Supports optional demultiplexing of the new attach stream system implemented in Remote API v1.6. * **entities** - containers and images are defined entities and not random static methods. * **run** - `dockerode` allow you to seamless run commands in a container ala `docker run`. * **tests** - `dockerode` really aims to have a good test set, allowing to follow `Docker` changes easily, quickly and painlessly. @@ -20,7 +20,7 @@ Why `dockerode` is different from other Docker node.js modules: ## Usage - * Input options are directly passed to Docker.io. Check [Docker Remote API documentation](http://docs.docker.io/en/latest/api/docker_remote_api/) for more details. + * Input options are directly passed to Docker.io. Check [Docker Remote API documentation](http://docs.docker.io/reference/api/docker_remote_api/) for more details. * Return values are unchanged from Docker, official Docker.io documentation will also apply to them. * Check the tests for more examples. @@ -51,11 +51,17 @@ container.remove(function (err, data) { //... ``` +You may also specify default options for each container's operations, which will always be used for the specified container and operation. + +``` js +container.defaultOptions.start.Binds = ["/tmp:/tmp:rw"]; +``` + ### Stopping all containers on a host ``` js -docker.listContainers(function(err, containers) { - containers.forEach(function(containerInfo) { +docker.listContainers(function (err, containers) { + containers.forEach(function (containerInfo) { docker.getContainer(containerInfo.Id).stop(cb); }); }); @@ -64,7 +70,7 @@ docker.listContainers(function(err, containers) { ### Building an Image ``` js -docker.buildImage('archive.tar', {t: imageName}, function(err, response){ +docker.buildImage('archive.tar', {t: imageName}, function (err, response){ //... }); ``` @@ -72,8 +78,8 @@ docker.buildImage('archive.tar', {t: imageName}, function(err, response){ ### Creating a container: ``` js -docker.createContainer({Image: 'ubuntu', Cmd: ['/bin/bash']}, function(err, container) { - container.start(function(err, data) { +docker.createContainer({Image: 'ubuntu', Cmd: ['/bin/bash']}, function (err, container) { + container.start(function (err, data) { //... }); }); @@ -84,18 +90,17 @@ docker.createContainer({Image: 'ubuntu', Cmd: ['/bin/bash']}, function(err, cont ``` js //tty:true -container.attach({stream: true, stdout: true, stderr: true, tty: true}, function(err, stream) { +container.attach({stream: true, stdout: true, stderr: true, tty: true}, function (err, stream) { stream.pipe(process.stdout); }); //tty:false -container.attach({stream: true, stdout: true, stderr: true, tty: false}, function(err, stream) { - //http://docs.docker.io/en/latest/api/docker_remote_api_v1.7/#post--containers-(id)-attach - //dockerode may demultiplex the streams for you :) +container.attach({stream: true, stdout: true, stderr: true, tty: false}, 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) { +docker.createImage({fromImage: 'ubuntu'}, function (err, stream) { stream.pipe(process.stdout); }); @@ -107,10 +112,11 @@ docker.createImage({fromImage: 'ubuntu'}, function(err, stream) { * `image` - container image * `cmd` - command to be executed * `stream` - stream(s) which will be used for execution output. +* `[create_options]` - options used for container creation. * `callback` - callback called when execution ends. ``` js -docker.run('ubuntu', ['bash', '-c', 'uname -a'], process.stdout, function(err, data, container) { +docker.run('ubuntu', ['bash', '-c', 'uname -a'], process.stdout, function (err, data, container) { console.log(data.StatusCode); }); ``` @@ -118,22 +124,31 @@ docker.run('ubuntu', ['bash', '-c', 'uname -a'], process.stdout, function(err, d or, if you want to split stdout and stderr (you must to pass `Tty:false` as an option for this to work) ``` js -docker.run('ubuntu', ['bash', '-c', 'uname -a'], [process.stdout, process.stderr], {Tty:false}, function(err, data, container) { +docker.run('ubuntu', ['bash', '-c', 'uname -a'], [process.stdout, process.stderr], {Tty:false}, function (err, data, container) { console.log(data.StatusCode); }); ``` +Run also returns an EventEmitter supporting the following events: container, stream, data. Allowing stuff like this: + +``` js +docker.run('ubuntu', ['bash', '-c', 'uname -a'], [process.stdout, process.stderr], {Tty:false}, function (err, data, container) { + //... +}).on('container', function (container) { + container.defaultOptions.start.Binds = ["/tmp:/tmp:rw"]; +}); +``` + ### Equivalent of `docker pull` in `dockerode`: * `repoTag` - container image name (optionally with tag) `myrepo/myname:withtag` -* `opts` - extra options passed to create image see [docker api](http://docs.docker.io/en/latest/api/docker_remote_api_v1.8/#create-an-image) +* `opts` - extra options passed to create image. * `callback` - callback called when execution ends. ``` js -docker.pull('myrepo/myname:tag', function(err, stream) { - // streaming output from pull... - // Also see: http://docs.docker.io/en/latest/api/docker_remote_api_v1.8/#create-an-image +docker.pull('myrepo/myname:tag', function (err, stream) { + // streaming output from pull... }); ``` diff --git a/lib/docker.js b/lib/docker.js index 386526b..1368d7e 100644 --- a/lib/docker.js +++ b/lib/docker.js @@ -78,7 +78,7 @@ Docker.prototype.buildImage = function(file, opts, callback) { callback = opts; opts = null; } - + var self = this; var opts = { path: '/build?', @@ -247,19 +247,19 @@ Docker.prototype.run = function(image, cmd, streamo, options, callback) { callback = options; options = {}; } - + var hub = new EventEmitter(); function handler(err, container) { if (err) return callback(err, container); - + hub.emit('container', container); container.attach({stream: true, stdout: true, stderr: true}, function handler(err, stream) { if (err) return callback(err, data); - hub.emit('stream', stream); - + hub.emit('stream', stream); + if (streamo) { if (streamo instanceof Array) { container.modem.demuxStream(stream, streamo[0], streamo[1]); @@ -299,7 +299,7 @@ Docker.prototype.run = function(image, cmd, streamo, options, callback) { _.extend(optsc, options); this.createContainer(optsc, handler); - + return hub; }; diff --git a/package.json b/package.json index 33841ed..973d08a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dockerode", "description": "Docker.io / Docker remote API implementation.", - "version": "1.2.10", + "version": "1.3.0", "author": "Pedro Dias ", "maintainers": [ "apocas " @@ -29,5 +29,95 @@ }, "engines": { "node": ">= 0.8" - } + }, + "contributors": [ + { + "name": "Pedro Dias", + "email": "petermdias@gmail.com", + "url": "https://github.com/apocas", + "contributions": 93 + }, + { + "name": "James Lal", + "email": "jlal@mozilla.com", + "url": "https://github.com/lightsofapollo", + "contributions": 12 + }, + { + "name": "Everton Ribeiro", + "email": "nuxlli@gmail.com", + "url": "https://github.com/nuxlli", + "contributions": 4 + }, + { + "name": "Sam Rijs", + "email": "srijs@airpost.net", + "url": "https://github.com/srijs", + "contributions": 3 + }, + { + "name": "Mike MacCana", + "email": "mike.maccana@gmail.com", + "url": "https://github.com/mikemaccana", + "contributions": 2 + }, + { + "url": "https://github.com/niclashoyer", + "contributions": 2 + }, + { + "name": "Alex Wolfe", + "email": "alexkwolfe@gmail.com", + "url": "https://github.com/alexkwolfe", + "contributions": 1 + }, + { + "name": "Vincent Woo", + "email": "me@vincentwoo.com", + "url": "https://github.com/vincentwoo", + "contributions": 1 + }, + { + "name": "Adam Duncan", + "email": "", + "url": "https://github.com/microadam", + "contributions": 1 + }, + { + "name": "Geoffrey Bachelet", + "email": "geoffrey.bachelet@gmail.com", + "url": "https://github.com/ubermuda", + "contributions": 1 + }, + { + "name": "Josh Matthews", + "email": "josh@jmatthews.us", + "url": "https://github.com/jmatth", + "contributions": 1 + }, + { + "name": "Kishore Nallan", + "email": "kishore@kishorelive.com", + "url": "https://github.com/kishorenc", + "contributions": 1 + }, + { + "name": "Mathias Buus", + "email": "mathiasbuus@gmail.com", + "url": "https://github.com/mafintosh", + "contributions": 1 + }, + { + "name": "Shannon Poole", + "email": "shannon.m.poole@gmail.com", + "url": "https://github.com/shannonmpoole", + "contributions": 1 + }, + { + "name": "Dan Williams", + "email": "me+github@deedubs.com", + "url": "https://github.com/deedubs", + "contributions": 1 + } + ] } diff --git a/test/docker.js b/test/docker.js index 27c4985..aa908c8 100644 --- a/test/docker.js +++ b/test/docker.js @@ -72,7 +72,7 @@ describe("#docker", function() { this.timeout(120000); // one image with one tag - var repoTag = 'lightsofapollo/test-taskenv:fail'; + var repoTag = 'ubuntu:latest'; // XXX: Should this be an extra abstraction in docker.js? function locateImage(image, callback) { @@ -121,18 +121,29 @@ describe("#docker", function() { describe("#run", function() { this.timeout(30000); - it('should report malformed request errors', function(done) { - function handler(err, data) { - expect(err).to.be.ok; - done(); + + it("should emit partial data", function(done) { + function handler(err, data, container) { + expect(err).to.be.null; + //container is created + expect(container).to.be.ok; + + container.remove(function(err, data) { + expect(err).to.be.null; + }); } - docker.run( - 'ubuntu', - 'exit 1', // this is an invalid parameter type (it should be an array) - process.stdout, - handler - ); + var ee = docker.run('ubuntu', ['bash', '-c', 'uname -a'], process.stdout, handler); + ee.on('container', function (container) { + expect(container).to.be.ok; + }); + ee.on('stream', function (stream) { + expect(stream).to.be.ok; + }); + ee.on('data', function (data) { + expect(data).to.be.ok; + done(); + }); }); it("should run a command", function(done) { @@ -161,8 +172,8 @@ describe("#docker", function() { container.inspect(function (err, info) { expect(err).to.be.null; - expect(info.Name).to.equal('/test') - }) + expect(info.Name).to.equal('/test'); + }); container.remove(function(err, data) { expect(err).to.be.null; diff --git a/test/test.tar b/test/test.tar index 0e64ea7..36717ff 100644 Binary files a/test/test.tar and b/test/test.tar differ