2020-12-02 07:35:26 +00:00
|
|
|
const spawn = require('child_process').spawn;
|
2020-11-16 13:23:28 +00:00
|
|
|
const execFile = require('child_process').execFile;
|
2020-11-14 01:38:56 +00:00
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
const docker = {
|
|
|
|
async run(image, commandArgs, options, execOptions) {
|
|
|
|
const args = commandArgs
|
|
|
|
? [image].concat(commandArgs)
|
|
|
|
: image;
|
|
|
|
const execMode = options.detach ? 'exec' : 'spawn';
|
|
|
|
|
|
|
|
const child = await this.exec('run',
|
|
|
|
args,
|
|
|
|
options,
|
|
|
|
execMode,
|
|
|
|
execOptions
|
|
|
|
);
|
|
|
|
return options.detach
|
|
|
|
? new Container(child.stdout.trim())
|
|
|
|
: child;
|
|
|
|
},
|
|
|
|
|
|
|
|
async build(url, options, execOptions) {
|
|
|
|
return await this.exec('build',
|
|
|
|
url,
|
|
|
|
options,
|
|
|
|
'spawn',
|
|
|
|
execOptions
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
async start(id, options) {
|
|
|
|
const ct = new Container(id);
|
|
|
|
await ct.start(options);
|
|
|
|
return ct;
|
|
|
|
},
|
|
|
|
|
|
|
|
async stop(id, options) {
|
|
|
|
const ct = new Container(id);
|
|
|
|
return await ct.stop(options);
|
|
|
|
},
|
|
|
|
|
|
|
|
async rm(id, options) {
|
|
|
|
const ct = new Container(id);
|
|
|
|
return await ct.rm(options);
|
|
|
|
},
|
|
|
|
|
|
|
|
async inspect(id, options) {
|
|
|
|
const ct = new Container(id);
|
|
|
|
return await ct.inspect(options);
|
|
|
|
},
|
|
|
|
|
|
|
|
async exec(command, args, options, execMode, execOptions) {
|
|
|
|
const execArgs = [command];
|
|
|
|
|
|
|
|
if (options)
|
|
|
|
for (const option in options) {
|
|
|
|
execArgs.push(`--${camelToSnake(option)}`);
|
|
|
|
if (typeof options[option] !== 'boolean')
|
|
|
|
execArgs.push(options[option]);
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
if (Array.isArray(args))
|
|
|
|
Array.prototype.push.apply(execArgs, args);
|
|
|
|
else if (args)
|
|
|
|
execArgs.push(args);
|
|
|
|
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
if (execMode == 'spawn') {
|
|
|
|
if (execOptions === true)
|
|
|
|
execOptions = {
|
|
|
|
stdio: [
|
|
|
|
process.stdin,
|
|
|
|
process.stdout,
|
|
|
|
process.stderr
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
const child = spawn('docker', execArgs, execOptions || undefined);
|
|
|
|
child.on('exit', code => {
|
|
|
|
if (code !== 0) {
|
|
|
|
const args = JSON.stringify(execArgs);
|
2020-12-04 09:15:29 +00:00
|
|
|
reject(new Error(`docker: ${args}: exit code ${code}`));
|
2020-12-02 07:35:26 +00:00
|
|
|
} else
|
|
|
|
resolve(code);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
execFile('docker', execArgs, (err, stdout, stderr) => {
|
|
|
|
if (err)
|
|
|
|
reject(err);
|
|
|
|
else
|
|
|
|
resolve({stdout, stderr});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
2020-12-02 07:35:26 +00:00
|
|
|
};
|
2020-11-14 01:38:56 +00:00
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
class Container {
|
2020-12-04 09:15:29 +00:00
|
|
|
constructor(id) {
|
|
|
|
if (!id)
|
|
|
|
throw new Error('Container id argument is required');
|
2020-12-02 07:35:26 +00:00
|
|
|
this.id = id;
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
async start(options) {
|
|
|
|
await docker.exec('start', this.id, options);
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
async stop(options) {
|
|
|
|
await docker.exec('stop', this.id, options);
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
async rm(options) {
|
|
|
|
await docker.exec('rm', this.id, options);
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
async inspect(options) {
|
|
|
|
const child = await docker.exec('inspect', this.id, options);
|
|
|
|
return JSON.parse(child.stdout);
|
2020-11-14 01:38:56 +00:00
|
|
|
}
|
2020-12-02 07:35:26 +00:00
|
|
|
}
|
2020-11-16 13:23:28 +00:00
|
|
|
|
2020-12-02 07:35:26 +00:00
|
|
|
function camelToSnake(str) {
|
|
|
|
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
|
|
|
|
}
|
|
|
|
|
2020-12-04 09:15:29 +00:00
|
|
|
module.exports = docker;
|
|
|
|
module.exports.Container = Container;
|