├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── lib ├── images.js ├── networks.js ├── nodes.js ├── services.js └── volumes.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 OptimalBits 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dolphin 2 | ![dolphin](https://d30y9cdsu7xlg0.cloudfront.net/png/29924-200.png) 3 | 4 | 5 | A fast, lightweight an modular library to interact with docker daemons. 6 | 7 | This module provides a thin layer to communicate with docker daemons in node. 8 | The api is promise and events based trying to follow the semantics of 9 | docker's remote api as closely as possible. 10 | 11 | 12 | # Install 13 | 14 | ```npm install dolphin``` 15 | 16 | 17 | # Usage 18 | 19 | ## Instantiation 20 | 21 | Before starting to interact with docker deamons you need to instantiate dolphin. 22 | If you are using docker-machine, and the env vars are set by ```docker-machine env mymachine```, 23 | then you can just instantiate it without args. If no env variables are set, it will use dockers 24 | default Unix domain socket: ```unix:///var/run/docker.sock```. 25 | 26 | ```js 27 | var dolphin = require('dolphin')(); 28 | ``` 29 | 30 | You can also instantiate it with an explicit url pointing to the docker daemon: 31 | 32 | ```js 33 | var Dolphin = require('dolphin'); 34 | 35 | var dolphin = Dolphin({ 36 | url: 'http://mydockerhost.com: 1234' 37 | }) 38 | ``` 39 | 40 | ### Version 41 | 42 | You can ask dolphin for the docker engine version installed: 43 | 44 | ```js 45 | dolphin.version().then(function(version){ 46 | ... 47 | }) 48 | ``` 49 | 50 | Or some system wide information: 51 | ```js 52 | dolphin.info().then(function(info){ 53 | ... 54 | }) 55 | ``` 56 | 57 | ## Images 58 | 59 | 60 | ## Containers 61 | 62 | You can get a list of all the containers running on the system using the container method: 63 | 64 | ```js 65 | dolphin.containers().then(function(containers){ 66 | // Containers contains an array of docker containers. 67 | // https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#list-containers 68 | }) 69 | 70 | // Query parameters are also supported, so that you can get a subset of the containers 71 | dolphin.containers({ 72 | all: {Boolean}, // Show all containers even stopped ones. 73 | limit: {Integer}, 74 | since: {Integer}, // Show containers created since given timestamp 75 | before: {Integer}, // Show containers created before given timestamp 76 | size: {Boolean}, 77 | filters: {Object}, // Eg. {"exited":0, "status":["restarting","running","paused","exited"]} 78 | }).then(function(containers){ 79 | 80 | }) 81 | ``` 82 | 83 | ### Container methods 84 | 85 | There are several useful methods for querying containers: 86 | 87 | ```js 88 | dolphin.containers.inspect(containerId).then(function(info){ 89 | // Container info 90 | }) 91 | ``` 92 | 93 | ```js 94 | dolphin.containers.logs(containerId).then(function(logs){ 95 | // Container logs 96 | }) 97 | ``` 98 | 99 | ```js 100 | dolphin.containers.changes(containerId).then(function(changes){ 101 | // Container changes 102 | }) 103 | ``` 104 | 105 | ```js 106 | dolphin.containers.export(containerId).then(function(export){ 107 | // Container info 108 | }) 109 | ``` 110 | 111 | ```js 112 | dolphin.containers.stats(containerId).then(function(stats){ 113 | // Container stats 114 | }) 115 | ``` 116 | 117 | ## Events 118 | 119 | A very powerful featue in dolphin is the ability to listen to events 120 | generated by docker deamons. 121 | 122 | It can show live or old events, depending on the options used: 123 | 124 | ```js 125 | dolphin.events({ 126 | since: Date.now() / 1000, 127 | until: Date.now() / 1000 128 | }).on('event', function(evt){ 129 | console.log(evt); 130 | }).on('error', function(err){ 131 | console.log('Error:', err); 132 | }); 133 | ``` 134 | 135 | See which events are produced by docker here: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/monitor-docker-s-events 136 | 137 | 138 | ## Volumes 139 | 140 | 141 | ## Networks 142 | 143 | 144 | ## Nodes 145 | 146 | 147 | ## Services 148 | 149 | 150 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var url = require('url'); 4 | var http = require('http'); 5 | var request = require('request'); 6 | var EventEmitter = require('events').EventEmitter; 7 | var Promise = require('bluebird'); 8 | var querystring = require('querystring'); 9 | var fs = require('fs'); 10 | var path = require('path'); 11 | var _ = require('lodash'); 12 | 13 | var images = require('./lib/images'); 14 | var nodes = require('./lib/nodes') 15 | var networks = require('./lib/networks'); 16 | var volumes = require('./lib/volumes'); 17 | var services = require('./lib/services'); 18 | 19 | var RESTART_WAIT = 5000; 20 | 21 | var Dolphin = function (opts) { 22 | if (!(this instanceof Dolphin)) { 23 | return new Dolphin(opts); 24 | } 25 | 26 | var env = this.env = process.env; 27 | if (typeof opts === 'string') { 28 | env = getMachineEnv(opts); 29 | this.env = _.extend(this.env, env); 30 | opts = {}; 31 | } 32 | 33 | opts = opts || {}; 34 | 35 | var _url = opts.url || env.DOCKER_HOST || '/var/run/docker.sock'; 36 | _url = url.parse(_url); 37 | if (_url.protocol) { 38 | var protocol = 'http'; 39 | if (env.DOCKER_TLS_VERIFY === '1' || _url.port === '2376') { 40 | protocol = 'https'; 41 | 42 | if (env.DOCKER_CERT_PATH) { 43 | opts.ca = fs.readFileSync(path.join(env.DOCKER_CERT_PATH, 'ca.pem')); 44 | opts.cert = fs.readFileSync(path.join(env.DOCKER_CERT_PATH, 'cert.pem')); 45 | opts.key = fs.readFileSync(path.join(env.DOCKER_CERT_PATH, 'key.pem')); 46 | } 47 | } 48 | this.url = protocol + '://' + _url.host; 49 | } else { 50 | // 51 | // Assume a UNIX domain socket if no protocol provided 52 | // 53 | this.url = _url.href; 54 | this.isSocket = true; 55 | } 56 | 57 | this.opts = opts; 58 | 59 | var _this = this; 60 | 61 | this.containers.inspect = function (id) { 62 | return _this._get('containers/' + id + '/json', null, _this.opts); 63 | } 64 | 65 | this.containers.logs = function (id) { 66 | // TODO: disable json parse 67 | return _this._get('containers/' + id + '/logs', null, _this.opts); 68 | } 69 | 70 | this.containers.changes = function (id) { 71 | return _this._get('containers/' + id + '/changes', null, _this.opts); 72 | } 73 | 74 | this.containers.export = function (id) { 75 | // TODO: disable json parse 76 | return _this._get('containers/' + id + '/export', null, _this.opts); 77 | } 78 | 79 | this.containers.stats = function (id) { 80 | // TODO: "getStream" 81 | return _this._get('containers/' + id + '/stats', null, _this.opts); 82 | } 83 | 84 | // 85 | // Attach methods 86 | // 87 | this.images = images(this); 88 | this.nodes = nodes(this); 89 | this.volumes = volumes(this); 90 | this.networks = networks(this); 91 | this.services = services(this); 92 | }; 93 | 94 | Dolphin.prototype.containers = function (query) { 95 | return this._get('containers/json', query, this.opts); 96 | } 97 | 98 | Dolphin.prototype.info = function () { 99 | return this._get('info', null, this.opts); 100 | } 101 | 102 | Dolphin.prototype.version = function () { 103 | return this._get('version', null, this.opts); 104 | } 105 | 106 | Dolphin.prototype.events = function (query) { 107 | var _this = this; 108 | var url = buildUrl(this.url, 'events', query, this.isSocket); 109 | var emitter = new EventEmitter; 110 | var latestTime; 111 | var req; 112 | var restartTimeout; 113 | 114 | emitter.abort = function () { 115 | req && req.abort(); 116 | clearTimeout(restartTimeout); 117 | } 118 | 119 | function startStreaming() { 120 | return request({ 121 | url: url, 122 | ca: _this.opts.ca, 123 | cert: _this.opts.cert, 124 | key: _this.opts.key, 125 | headers: _this.isSocket ? { host: 'http' } : void 0 126 | }).on('data', function (chunk) { 127 | var evt; 128 | try { 129 | evt = JSON.parse(chunk.toString()); 130 | latestTime = evt.time; 131 | emitter.emit('event', evt); 132 | } catch (err) { 133 | emitter.emit('error', err); 134 | } 135 | }).on('error', function (err) { 136 | emitter.emit('error', err); 137 | restart(); 138 | }).on('end', function () { 139 | restart(); 140 | }).on('close', function (doc) { 141 | restart(); 142 | }).on('response', function (res) { 143 | if (res.statusCode === 200) { 144 | emitter.emit('connected'); 145 | } else { 146 | emitter.emit('error', Error("Error connecting with status " + res.statusCode)); 147 | } 148 | }); 149 | } 150 | 151 | function restart() { 152 | setTimeout(function () { 153 | if (latestTime) { 154 | opts.since = latestTime; 155 | } 156 | req = startStreaming(); 157 | }, RESTART_WAIT); 158 | } 159 | 160 | req = startStreaming(emitter); 161 | 162 | return emitter; 163 | } 164 | 165 | Dolphin.prototype.docker = function (args) { 166 | var _this = this; 167 | var child = require('child_process'); 168 | return new Promise(function (resolve, reject) { 169 | var docker = child.spawn('docker', args, { env: _this.env }); 170 | var result = ''; 171 | var err = ''; 172 | 173 | docker.stdout.on('data', function (data) { 174 | result += data; 175 | }); 176 | 177 | docker.stderr.on('data', function (data) { 178 | err += data; 179 | }); 180 | 181 | docker.on('close', function (code) { 182 | return code === 0 ? resolve(result.toString()) : reject(err); 183 | }); 184 | }); 185 | } 186 | 187 | /** 188 | * @param {string | Buffer | string[]} str 189 | * @private 190 | */ 191 | function trimTerminator(str) { 192 | if (Array.isArray(str)) { 193 | return trimTerminator(str.join('')); 194 | } 195 | 196 | if (typeof str !== 'string') { 197 | str = str.toString(); 198 | } 199 | 200 | return str.replace(/[\r\n]+$/, ''); 201 | } 202 | 203 | /** 204 | * Executes a docker command by spawning a new docker instance. This is more flexible than the docker() function. 205 | * 206 | * @param { string[] } args Args that will be used when calling the docker command. 207 | * @param { (data: string, err: string) => void } [cb] Optional callback function. Will be called on every buffer of data received. 208 | * 209 | * @returns { Promise<{ stdout: string; stderr: string; }> } A Promise containaing the code, signal, stdout, and stderr. 210 | */ 211 | Dolphin.prototype.cmd = function cmd(args, cb) { 212 | if (cb && typeof cb !== 'function') { 213 | throw new Error('cb needs to be a function'); 214 | } 215 | 216 | return new Promise((resolve, reject) => { 217 | const child = require('child_process'); 218 | const childProcess = child.spawn('docker', args, { env: this.env }); 219 | 220 | /** @type {string[]} */ 221 | const stdout = []; 222 | 223 | /** @type {string[]} */ 224 | const stderr = []; 225 | 226 | const dataProcessor = err => { 227 | return data => { 228 | (err ? stderr : stdout).push(data); 229 | 230 | if (cb) { 231 | data = trimTerminator(data); 232 | return err ? cb(null, data) : cb(data); 233 | } 234 | }; 235 | }; 236 | 237 | childProcess.stdout.on('data', dataProcessor(false)); 238 | childProcess.stderr.on('data', dataProcessor(true)); 239 | 240 | childProcess.on('close', (code, signal) => { 241 | const _stdout = trimTerminator(stdout); 242 | const _stderr = trimTerminator(stderr); 243 | 244 | if (code === 0) { 245 | return resolve({ 246 | stdout: _stdout, 247 | stderr: _stderr 248 | }); 249 | } 250 | 251 | const err = new Error('An error has occured while executing the docker command.'); 252 | err.code = code; 253 | err.signal = signal; 254 | err.stdout = _stdout; 255 | err.stderr = _stderr; 256 | return reject(err); 257 | }); 258 | }); 259 | }; 260 | 261 | Dolphin.prototype._list = function (bucket, idOrFilters, opts) { 262 | var query; 263 | if (idOrFilters) { 264 | if (_.isString(idOrFilters)) { 265 | return this._get(bucket + '/' + idOrFilters, null, opts); 266 | } 267 | query = { 268 | filters: idOrFilters 269 | } 270 | } 271 | return this._get(bucket, query, opts); 272 | } 273 | 274 | Dolphin.prototype._get = function (path, query, args) { 275 | return this._request('GET', path, query, args); 276 | } 277 | 278 | Dolphin.prototype._post = function (path, body, args) { 279 | args = args ? _.clone(args) : {}; 280 | args.body = body; 281 | return this._request('POST', path, null, args); 282 | } 283 | 284 | Dolphin.prototype._delete = function (path, args) { 285 | return this._request('DELETE', path, null, args); 286 | } 287 | 288 | Dolphin.prototype._request = function (method, path, query, args) { 289 | var opts = args ? _.clone(args) : {}; 290 | opts.url = buildUrl(this.url, path, query, this.isSocket); 291 | opts.method = method; 292 | opts.json = true; 293 | 294 | if (this.isSocket) { 295 | // Workaround for request bug https://github.com/request/request/issues/2327 296 | opts.headers = { host: 'http' }; 297 | } 298 | 299 | return new Promise(function (resolve, reject) { 300 | request(opts, function (err, response, body) { 301 | if (err) return reject(err); 302 | 303 | if ([200, 201, 204].indexOf(response.statusCode) != -1) { 304 | try { 305 | resolve(body); 306 | //resolve(JSON.parse(body)); 307 | } catch (err) { 308 | reject(err); 309 | } 310 | } else if (response.statusCode === 404 && opts.method !== 'POST') { 311 | resolve(); 312 | } else { 313 | return reject(Error('Request failed: ' + response.statusCode + ':' + JSON.stringify(body))); 314 | } 315 | }); 316 | }); 317 | } 318 | 319 | function buildUrl(url, path, query, isSocket) { 320 | if (isSocket) { 321 | url = 'http://unix:' + url + ':/' + path; 322 | } else { 323 | url = url + '/' + path; 324 | } 325 | if (query) { 326 | if (query.filters) { 327 | query.filters = filtersToJSON(query.filters); 328 | } 329 | url += '?' + querystring.stringify(query); 330 | } 331 | return url; 332 | } 333 | 334 | function filtersToJSON(filters) { 335 | var keys = Object.keys(filters); 336 | keys.forEach(function (key) { 337 | filters[key] = [filters[key].toString()]; 338 | }) 339 | return JSON.stringify(filters); 340 | } 341 | 342 | /** 343 | * Returns the env vars for the given docker machine. 344 | */ 345 | function getMachineEnv(machine) { 346 | var child = require('child_process'); 347 | var result = child.spawnSync('docker-machine', ['env', machine]); 348 | 349 | if (result.status === 0) { 350 | var str = result.stdout.toString(); 351 | var expr = str 352 | .replace(new RegExp('export ', 'g'), 'envs.') 353 | .split('\n') 354 | .filter(function (line) { 355 | return line[0] !== '#'; 356 | }).join(';') 357 | 358 | var envs = {}; 359 | eval(expr); 360 | return envs; 361 | } else { 362 | throw Error(result.stderr) 363 | } 364 | } 365 | 366 | module.exports = Dolphin; 367 | -------------------------------------------------------------------------------- /lib/images.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function (dolphin) { 4 | var opts = dolphin.opts; 5 | 6 | /** 7 | * 8 | * filters – a JSON encoded value of the filters (a map[string][]string) to process on the images list. Available filters: 9 | dangling=true 10 | label=key or label="key=value" of an image label 11 | before=([:], or ) 12 | since=([:], or ) 13 | **/ 14 | var images = function (imageName) { 15 | //return dolphin._list('images', filters, opts); 16 | return dolphin._get('images/' + imageName + '/json', null, opts); 17 | } 18 | 19 | /** 20 | * 21 | * @param {string} url 22 | * @param {string} name 23 | * @param {string[]} [versions] 24 | * @param {{Labels?: object; buildargs?: object; }} [params] 25 | * @returns {Promise<{ Id: string }>} 26 | */ 27 | images.build = function (url, name, versions = [], params = {}) { 28 | if (typeof url !== 'string') { 29 | throw new Error('url needs to be a string'); 30 | } 31 | 32 | if (typeof name !== 'string') { 33 | throw new Error('name needs to be a string'); 34 | } 35 | 36 | if(versions && !Array.isArray(versions)) { 37 | throw new Error('versions needs to be an array'); 38 | } 39 | 40 | const args = ['build']; 41 | 42 | if (versions && versions.length > 0) { 43 | for (const version of versions) { 44 | args.push('-t', `${name}:${version}`); 45 | } 46 | } else { 47 | // do not use any versions but still use tag 48 | args.push('-t', name); 49 | } 50 | 51 | if (params) { 52 | if(typeof params !== 'object') { 53 | throw new Error('params needs to be an object'); 54 | } 55 | 56 | for (const param of [ 57 | { key: 'Labels', arg: '--label' }, 58 | { key: 'buildargs', arg: '--build-arg' } 59 | ]) { 60 | const obj = params[param.key]; 61 | 62 | if (obj && typeof obj === 'object') { 63 | Object 64 | .keys(obj) 65 | .forEach(key => { 66 | args.push(param.arg, `${key}=${obj[key]}`); 67 | }); 68 | } 69 | } 70 | } 71 | 72 | args.push('-q') 73 | args.push(url); 74 | 75 | // We use docker command line since building images is quite a complex operation. 76 | return dolphin.cmd(args).then(({ stdout }) => { 77 | return { 78 | Id: stdout.trim() 79 | }; 80 | }); 81 | } 82 | 83 | images.push = function (image, tag) { 84 | var url = 'images/' + image + '/push'; 85 | if (tag) { 86 | url += '?tag=' + tag; 87 | } 88 | return dolphin._post(url, null, opts); 89 | } 90 | 91 | images.tag = function (nameOrId, repo, tag) { 92 | var url = 'images/' + nameOrId + '/tag?repo=' + repo; 93 | if (tag) { 94 | url += '&tag=' + tag; 95 | } 96 | return dolphin._post(url, null, opts); 97 | } 98 | 99 | // 100 | // TODO: registry auth. 101 | // TODO: default registries, etc. 102 | // 103 | var request = require('request'); 104 | images.manifest = function (name, tag) { 105 | return new Promise(function (resolve, reject) { 106 | var splitted = name.split('/'); 107 | if (splitted.length > 1) { 108 | var registry = splitted[0]; 109 | var repo = splitted[1]; 110 | var opts = { 111 | url: 'https://' + registry + '/v2/' + repo + '/manifests/' + tag, 112 | method: 'GET', 113 | json: true, 114 | } 115 | 116 | request(opts, function (err, response, body) { 117 | if (err) return reject(err); 118 | resolve(body); 119 | }); 120 | } else { 121 | resolve(); 122 | } 123 | }); 124 | } 125 | 126 | return images; 127 | } 128 | -------------------------------------------------------------------------------- /lib/networks.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function(dolphin){ 4 | var opts = dolphin.opts; 5 | 6 | /** 7 | * driver= Matches a network’s driver. 8 | id= Matches all or part of a network id. 9 | label= or label== of a network label. 10 | name= Matches all or part of a network name. 11 | type=["custom"|"builtin"] Filters networks by type. The custom keyword returns all user-defined networks. 12 | **/ 13 | var networks = function(filters){ 14 | return dolphin._list('networks', filters, opts); 15 | } 16 | 17 | /** 18 | * 19 | * Name - The new network’s name. this is a mandatory field 20 | CheckDuplicate - Requests daemon to check for networks with same name 21 | Driver - Name of the network driver plugin to use. Defaults to bridge driver 22 | Internal - Restrict external access to the network 23 | IPAM - Optional custom IP scheme for the network 24 | EnableIPv6 - Enable IPv6 on the network 25 | Options - Network specific options to be used by the drivers 26 | Labels - Labels to set on the network, specified as a map: {"key":"value" [,"key2":"value2"]} 27 | */ 28 | networks.create = function (params) { 29 | // return dolphin._post('networks/create', params, opts); 30 | 31 | // Use docker cmd directly since this endpoint is buggy and complex 32 | var args = ['network', 'create', '--driver', params.Driver]; 33 | if(params.Internal){ 34 | args.push('--internal'); 35 | } 36 | args.push(params.Name); 37 | 38 | return dolphin.cmd(args).then(({ stdout }) => { 39 | return { 40 | Id: stdout.trim() 41 | }; 42 | }); 43 | } 44 | 45 | networks.connect = function (containerId) { 46 | return dolphin._post('networks/create', {container: containerId}, opts); 47 | } 48 | 49 | networks.diconnect = function (containerId, force) { 50 | return dolphin._post('networks/create', {container: containerId, force: force}, opts); 51 | } 52 | 53 | networks.remove = function (networkId) { 54 | return dolphin._delete('networks/' + networkId, opts); 55 | } 56 | 57 | return networks; 58 | } 59 | -------------------------------------------------------------------------------- /lib/nodes.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(dolphin){ 3 | var opts = dolphin.opts; 4 | 5 | /** 6 | * id= 7 | name= 8 | membership=(pending|accepted|rejected)` 9 | role=(worker|manager)` 10 | **/ 11 | var nodes = function(filters){ 12 | return dolphin._list('nodes', filters, opts); 13 | } 14 | 15 | /* 16 | { 17 | "Availability": "active", 18 | "Name": "node-name", 19 | "Role": "manager", 20 | "Labels": { 21 | "foo": "bar" 22 | } 23 | } 24 | */ 25 | nodes.update = function (nodeId, params, version) { 26 | return dolphin._post('nodes/' + nodeId + '/update?version=' + version, params, opts); 27 | } 28 | 29 | nodes.remove = function (nodeId) { 30 | return dolphin._delete('nodes/' + nodeId, opts); 31 | } 32 | 33 | return nodes; 34 | } 35 | -------------------------------------------------------------------------------- /lib/services.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | module.exports = function(dolphin){ 4 | var opts = dolphin.opts; 5 | 6 | /** 7 | * Gets services. 8 | * @params id{String} or filters{Object} Optional parameters. 9 | id= 10 | name= 11 | **/ 12 | var services = function(filters){ 13 | return dolphin._list('services', filters, opts); 14 | } 15 | 16 | /** 17 | * Creates a service. For params check 18 | * https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/create-a-network 19 | */ 20 | services.create = function (params) { 21 | return dolphin._post('services/create', params, opts); 22 | } 23 | 24 | /** 25 | * Updates a service. Same params as create. 26 | * 27 | */ 28 | services.update = function (id, version, params) { 29 | return dolphin._post('services/' + id + '/update?version=' + version, params, opts); 30 | } 31 | 32 | /** 33 | * Removes a service. 34 | */ 35 | services.remove = function (serviceId) { 36 | return dolphin._delete('services/' + serviceId, opts); 37 | } 38 | 39 | return services; 40 | } 41 | -------------------------------------------------------------------------------- /lib/volumes.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function(dolphin){ 4 | var opts = dolphin.opts; 5 | 6 | /** 7 | * name= Matches all or part of a volume name. 8 | dangling= When set to true (or 1), returns all volumes that are “dangling” (not in use by a container). When set to false (or 0), only volumes that are in use by one or more containers are returned. 9 | driver= Matches all or part of a volume driver name. 10 | **/ 11 | var volumes = function(filters){ 12 | return dolphin._list('volumes', filters, opts); 13 | } 14 | 15 | /** 16 | * 17 | * Name - The new volume’s name. If not specified, Docker generates a name. 18 | Driver - Name of the volume driver to use. Defaults to local for the name. 19 | DriverOpts - A mapping of driver options and values. These options are passed directly to the driver and are driver specific. 20 | Labels - Labels to set on the volume, specified as a map: {"key":"value","key2":"value2"} 21 | */ 22 | volumes.create = function (params) { 23 | return dolphin._post('volumes/create', params, opts); 24 | } 25 | 26 | volumes.remove = function (volumeId) { 27 | return dolphin._delete('volumes/' + volumeId, opts); 28 | } 29 | 30 | return volumes; 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dolphin", 3 | "version": "0.1.14", 4 | "description": "A fast and lightweight module to interact with docker deamons", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "gulp test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/OptimalBits/dolphin.git" 12 | }, 13 | "keywords": [ 14 | "docker" 15 | ], 16 | "author": "Manuel Astudillo", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/OptimalBits/dolphin/issues" 20 | }, 21 | "homepage": "https://github.com/OptimalBits/dolphin", 22 | "dependencies": { 23 | "bluebird": "^2.9.24", 24 | "lodash": "^4.15.0", 25 | "request": "^2.65.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | //var dolphin = require('../')('http://localhost:9999/'); 2 | var dolphin = require('../')(); 3 | 4 | dolphin.events({ 5 | since: Date.now() / 1000, 6 | until: Date.now() / 1000 7 | }).on('event', function(evt){ 8 | console.log(evt); 9 | }).on('error', function(err){ 10 | console.log('Error:', err); 11 | }); 12 | 13 | 14 | /* 15 | dolphin.version().then(function(info){ 16 | console.log(info); 17 | }) 18 | 19 | dolphin.info().then(function(info){ 20 | console.log(info); 21 | }) 22 | */ 23 | /* 24 | dolphin.containers 25 | .inspect('b6905639cab3aecc33e59ccb6c4c69cfcde6b813eb00efadb5191c3c5b7257e4') 26 | .then(function(container){ 27 | console.log(container); 28 | }, function(err){ 29 | console.log(err); 30 | }); 31 | */ 32 | 33 | /* 34 | dolphin.version().then(function(info){ 35 | console.log(info); 36 | }) 37 | */ 38 | 39 | dolphin.containers({filters: '{"status":["running"]}'}).then(function(info){ 40 | console.log(info); 41 | console.log(info[1].Ports); 42 | }) 43 | --------------------------------------------------------------------------------