Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dockerode-compose

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dockerode-compose - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

test/assets/wordpress_original.yml

14

compose.js

@@ -43,10 +43,16 @@ const yaml = require('js-yaml');

//ToDo: create a version with followprogress with onFinished
async pull(serviceN) {
async pull(serviceN, options) {
var streams = [];
var serviceNames = (serviceN !== undefined) ? [serviceN] : tools.sortServices(this.recipe);
var serviceNames = (serviceN === undefined || serviceN === null) ? tools.sortServices(this.recipe) : [serviceN];
for (var serviceName of serviceNames) {
var service = this.recipe.services[serviceName];
try {
streams.push(await this.docker.pull(service.image));
var stream = await this.docker.pull(service.image);
streams.push(stream);
if (options && options.verbose) {
stream.pipe(process.stdout);
}
if (options === undefined || (options && options.streams !== true)) {
await new Promise(fulfill => stream.once('end', fulfill));
}
} catch (e) {

@@ -53,0 +59,0 @@ throw e;

@@ -5,3 +5,3 @@ var Dockerode = require('dockerode');

var docker = new Dockerode();
var compose = new DockerodeCompose(docker, './test/assets/wordpress.yml', 'wordpress');
var compose = new DockerodeCompose(docker, './test/assets/wordpress_original.yml', 'wordpress');

@@ -8,0 +8,0 @@ (async () => {

@@ -11,4 +11,4 @@ module.exports = async function (docker, projectName, recipe, output) {

if (err.statusCode == 409 && err.json.message.includes("already exists")) {
let returnedNetwork = await docker.listNetworks({ "filters": { "name": [projectName + '_' + networkName] } })
networks.push({ "name": projectName + '_' + networkName, "network": await docker.getNetwork(returnedNetwork[0].Id) })
let returnedNetwork = await docker.listNetworks({ "filters": { "name": [projectName + '_' + networkName] } });
networks.push({ "name": projectName + '_' + networkName, "network": await docker.getNetwork(returnedNetwork[0].Id) });
} else {

@@ -38,3 +38,3 @@ throw err;

'Options': network.ipam.options
}
};
if (network.ipam.config !== undefined) {

@@ -46,3 +46,3 @@ opts.IPAM['Config'] = {

'AuxAddress': network.ipam.config.aux_addresses
}
};
}

@@ -63,4 +63,4 @@ }

if (err.statusCode == 409 && err.json.message.includes("already exists")) {
let returnedNetwork = await docker.listNetworks({ "filters": { "name": [projectName + '_default'] } })
networks.push({ "name": projectName + '_' + networkName, "network": await docker.getNetwork(returnedNetwork[0].Id) })
let returnedNetwork = await docker.listNetworks({ "filters": { "name": [projectName + '_default'] } });
networks.push({ "name": projectName + '_' + networkName, "network": await docker.getNetwork(returnedNetwork[0].Id) });
} else {

@@ -67,0 +67,0 @@ throw err;

const tools = require('./tools');
const fs = require('fs');

@@ -24,3 +25,3 @@ module.exports = async function (docker, projectName, recipe, output) {

for (let index = 0; index < service.networks.length; index++) {
let networkName = projectName + '_' + service.networks[index]
let networkName = projectName + '_' + service.networks[index];
let networkTemplate = {

@@ -31,9 +32,9 @@ 'NetworkingConfig': {

}
}
};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName] = {};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = [serviceName]
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = [serviceName];
if (index === 0)
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig;
networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig)
networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig);
}

@@ -44,3 +45,3 @@ } else {

let network = service.networks[networkNames[index]] || {};
let networkName = projectName + '_' + networkNames[index]
let networkName = projectName + '_' + networkNames[index];
let networkTemplate = {

@@ -51,25 +52,25 @@ 'NetworkingConfig': {

}
}
networkTemplate.NetworkingConfig.EndpointsConfig[networkName] = {}
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['IPAMConfig'] = {}
};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName] = {};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['IPAMConfig'] = {};
if (network.aliases !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = network.aliases
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = network.aliases;
}
if (network.ipv4_address !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv4Address'] = network.ipv4_address
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv4Address'] = network.ipv4_address;
}
if (network.ipv6_address !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv6Address'] = network.ipv6_address
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv6Address'] = network.ipv6_address;
}
if (network.link_local_ips !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['LinkLocalIPs'] = network.link_local_ips
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['LinkLocalIPs'] = network.link_local_ips;
}
if (network.priority !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = network.priority
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = network.priority;
} else {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = 0
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = 0;
}
if (index === 0)
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig
networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig)
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig;
networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig);
}

@@ -87,2 +88,3 @@ }

// Can be used VolumesFrom from API DIRECTLY inside HostConfig :(
if (service.volumes_from) {

@@ -116,11 +118,11 @@ for (var volume_from of service.volumes_from) {

if (service.stop_grace_period !== undefined) {
let period = parseInt(service.stop_grace_period)
let period = parseInt(service.stop_grace_period);
if (service.stop_grace_period == period) {
opts.StopTimeout = service.stop_grace_period;
} else if (service.stop_grace_period.includes('m') && service.stop_grace_period.includes('s')) {
let minutes = parseInt(service.stop_grace_period.substring(0, service.stop_grace_period.indexOf('m')))
let seconds = parseInt(service.stop_grace_period.substring(service.stop_grace_period.indexOf('m') + 1, service.stop_grace_period.indexOf('s')))
opts.StopTimeout = (minutes * 60) + seconds
let minutes = parseInt(service.stop_grace_period.substring(0, service.stop_grace_period.indexOf('m')));
let seconds = parseInt(service.stop_grace_period.substring(service.stop_grace_period.indexOf('m') + 1, service.stop_grace_period.indexOf('s')));
opts.StopTimeout = (minutes * 60) + seconds;
} else {
opts.StopTimeout = service.stop_grace_period.substring(0, service.stop_grace_period.length - 2)
opts.StopTimeout = service.stop_grace_period.substring(0, service.stop_grace_period.length - 2);
}

@@ -131,2 +133,9 @@ }

}
if (service.expose !== undefined) {
var ports = {};
for (var port of service.expose) {
ports[port + '/tcp'] = {};
}
opts.ExposedPorts = ports;
}
if (service.tty !== undefined) {

@@ -147,10 +156,31 @@ opts.Tty = service.tty;

if (p[1] === undefined)
p[1] = ''
labels[p[0]] = p[1]
p[1] = '';
labels[p[0]] = p[1];
}
opts.Labels = labels
opts.Labels = labels;
} else {
opts.Labels = service.labels
opts.Labels = service.labels;
}
}
if (service.healthcheck !== undefined) {
let healthcheck = {};
healthcheck.Test = service.healthcheck.test;
healthcheck.Interval = convertFancyDurationToMs(service.healthcheck.interval);
healthcheck.Timeout = convertFancyDurationToMs(service.healthcheck.timeout);
healthcheck.Retries = service.healthcheck.retries;
healthcheck.StartPeriod = convertFancyDurationToMs(service.healthcheck.start_period);
opts.Healthcheck = healthcheck;
}
if (service.command !== undefined) {
opts.Cmd = service.command;
}
if (service.entrypoint !== undefined) {
if (Array.isArray(service.entrypoint)) {
opts.Entrypoint = service.entrypoint;
} else {
let entrypoint = [];
entrypoint.push(service.entrypoint);
opts.Entrypoint = entrypoint;
}
}
try {

@@ -161,9 +191,9 @@ var container = await docker.createContainer(opts);

let networkNames = Object.keys(networksToAttach[0]);
let network = findNetwork(output, networkNames[0])
await network.disconnect({ 'Container': container.id })
let networksToAttachSorted = tools.sortNetworksToAttach(networksToAttach)
let network = findNetwork(output, networkNames[0]);
await network.disconnect({ 'Container': container.id });
let networksToAttachSorted = tools.sortNetworksToAttach(networksToAttach);
for (var networkToAttach of networksToAttachSorted) {
let networkName = Object.keys(networkToAttach);
let network = findNetwork(output, networkName)
await network.connect({ 'Container': container.id, 'EndpointConfig': networkToAttach[networkName] })
let network = findNetwork(output, networkName);
await network.connect({ 'Container': container.id, 'EndpointConfig': networkToAttach[networkName] });
}

@@ -199,9 +229,98 @@

if (service.ports && service.ports.length > 0) {
var ports = {};
for (var portb of service.ports) {
var p = portb.split(':');
ports[p[1] + '/tcp'] = [{ 'HostPort': p[0] }]
if (service.ports !== undefined) {
if (typeof service.ports[0] === 'object') {
// LONG SYNTAX
// !!! INCOMPLETE - NOT USING DIFFERENT MODES - `mode`: `host` for publishing a host port on each node, or `ingress` for a port to be load balanced.
var ports = {};
for (var port of service.ports) {
ports[port.target + '/' + port.protocol] = [{ 'HostPort': port.published.toString() }];
}
output['PortBindings'] = ports;
} else {
// SHORT SYNTAX
// TODO: SIMPLIFY THIS BLOCK OF CODE! MAYBE!
var ports = {};
for (var port of service.ports) {
var port_split = port.split(':');
if (port_split.length == 2) {
// "xxxx:xxxx"
if (port_split[1].includes('-')) {
// "9090-9091:8080-8081"
let split_port_split0 = port_split[0].split('-');
let split_port_split0_array = [];
split_port_split0_array = fillPortArray(parseInt(split_port_split0[0]), parseInt(split_port_split0[1]));
let split_port_split1 = port_split[1].split('-');
let split_port_split1_array = [];
split_port_split1_array = fillPortArray(parseInt(split_port_split1[0]), parseInt(split_port_split1[1]));
for (let index in split_port_split0_array) {
ports[split_port_split1_array[index] + '/tcp'] = [{ 'HostPort': split_port_split0_array[index].toString() }];
}
} else if (port_split[0].includes('-')) {
// "3000-3005"
let split_port_split = port_split[0].split('-');
ports[port_split[1] + '/tcp'] = [];
for (let i = split_port_split[0]; i <= split_port_split[1]; i++) {
ports[port_split[1] + '/tcp'].push({ 'HostPort': i.toString() });
}
} else if (port_split[1].includes('/')) {
// "6060:6060/udp"
ports[port_split[1]] = [{ 'HostPort': port_split[0] }];
} else {
// "8000:8000"
ports[port_split[1] + '/tcp'] = [{ 'HostPort': port_split[0] }];
}
} else if (port_split.length == 3) {
// "x.x.x.x:xxxx:xxxx"
if (port_split[2].includes('-')) {
// "127.0.0.1:5000-5010:5000-5010"
let split_port_split1 = port_split[1].split('-');
let split_port_split1_array = [];
split_port_split1_array = fillPortArray(parseInt(split_port_split1[0]), parseInt(split_port_split1[1]));
let split_port_split2 = port_split[2].split('-');
let split_port_split2_array = [];
split_port_split2_array = fillPortArray(parseInt(split_port_split2[0]), parseInt(split_port_split2[1]));
for (let index in split_port_split1_array) {
ports[split_port_split2_array[index] + '/tcp'] = [{ 'HostPort': split_port_split1_array[index].toString(), 'HostIp': port_split[0] }];
}
} else if (port_split[1] == '') {
// "127.0.0.1::5000
ports[port_split[2] + '/tcp'] = [{ 'HostPort': port_split[2], 'HostIp': port_split[0] }];
} else {
// "127.0.0.1:8001:8001"
ports[port_split[2] + '/tcp'] = [{ 'HostPort': port_split[1], 'HostIp': port_split[0] }];
}
} else {
// "xxxx"
if (port_split[0].includes('-')) {
// "3000-3005"
let split_port_split = port_split[0].split('-');
for (let i = split_port_split[0]; i <= split_port_split[1]; i++) {
ports[i + '/tcp'] = [{ 'HostPort': i.toString() }];
}
} else {
// "3000"
ports[port + '/tcp'] = [{ 'HostPort': port }];
}
}
}
output['PortBindings'] = ports;
}
output['PortBindings'] = ports;
}

@@ -307,12 +426,12 @@

var p = sysctlsb.split('=');
sysctls[p[0]] = p[1]
sysctls[p[0]] = p[1];
}
output.Sysctls = sysctls
output.Sysctls = sysctls;
} else {
let sysctlKeys = Object.keys(service.sysctls)
let newSysctls = {}
let sysctlKeys = Object.keys(service.sysctls);
let newSysctls = {};
for (var key of sysctlKeys) {
newSysctls[key] = service.sysctls[key].toString();
}
output.Sysctls = newSysctls
output.Sysctls = newSysctls;
}

@@ -344,5 +463,5 @@ }

let ulimitsKeys = Object.keys(service.ulimits);
let ulimitsArray = []
let ulimitsArray = [];
for (var key of ulimitsKeys) {
let ulimitsObject = {}
let ulimitsObject = {};
if (typeof service.ulimits[key] === 'object') {

@@ -362,2 +481,37 @@ ulimitsObject.Name = key;

}
if (service.blkio_config !== undefined) {
if (service.blkio_config.weight !== undefined) {
output.BlkioWeight = service.blkio_config.weight;
}
if (service.blkio_config.weight_device !== undefined) {
let weight_device = [{}];
weight_device[0]['Path'] = service.blkio_config.weight_device[0].path;
weight_device[0]['Weight'] = service.blkio_config.weight_device[0].weight;
output.BlkioWeightDevice = weight_device;
}
if (service.blkio_config.device_read_bps !== undefined) {
output.BlkioDeviceReadBps = convertSizeStringToByteValue(service.blkio_config.device_read_bps);
}
if (service.blkio_config.device_read_iops !== undefined) {
let device_read_iops = [{}];
device_read_iops[0]['Path'] = service.blkio_config.device_read_iops[0].path;
device_read_iops[0]['Rate'] = service.blkio_config.device_read_iops[0].rate;
output.BlkioDeviceReadIOps = device_read_iops;
}
if (service.blkio_config.device_write_bps !== undefined) {
output.BlkioDeviceWriteBps = convertSizeStringToByteValue(service.blkio_config.device_write_bps);
}
if (service.blkio_config.device_write_iops !== undefined) {
let device_write_iops = [{}];
device_write_iops[0]['Path'] = service.blkio_config.device_write_iops[0].path;
device_write_iops[0]['Rate'] = service.blkio_config.device_write_iops[0].rate;
output.BlkioDeviceWriteIOps = device_write_iops;
}
}
if (service.logging !== undefined) {
let logging = {};
logging.Type = service.logging.driver;
logging.Config = service.logging.options;
output.LogConfig = logging;
}
return output;

@@ -374,3 +528,3 @@ }

if (type == 'ro') {
aux += ':ro'
aux += ':ro';
}

@@ -417,6 +571,24 @@ output['Binds'].push(aux);

var envsNames = Object.keys(service.environment || []);
for (var envName of envsNames) {
output.push(envName + '=' + service.environment[envName])
if (service.env_file !== undefined) {
if (Array.isArray(service.env_file)) {
for (let env_file_path of service.env_file) {
buildEnvVarsFromFile(env_file_path, output);
}
} else {
buildEnvVarsFromFile(service.env_file, output);
}
}
if (service.environment !== undefined) {
if (Array.isArray(service.environment)) {
for (let environment_line of service.environment) {
output.push(environment_line);
}
} else {
var envsNames = Object.keys(service.environment);
for (var envName of envsNames) {
output.push(envName + '=' + service.environment[envName]);
}
}
}
return output;

@@ -429,4 +601,74 @@ }

if (network.name == name)
return network.network
return network.network;
}
}
// TODO: OPTIMIZE!
var convertSizeStringToByteValue = function (obj) {
let rate = obj[0].rate.toLowerCase();
let new_obj = [{}];
if (rate.includes('k')) {
if (rate.indexOf('k') == rate.length - 1) {
rate = rate.replace('k', '');
} else if (rate.indexOf('k') == rate.length - 2) {
rate = rate.replace('kb', '');
}
new_obj[0]['Path'] = obj[0].path;
new_obj[0]['Rate'] = rate * 1024;
return new_obj;
} else if (rate.includes('m')) {
if (rate.indexOf('m') == rate.length - 1) {
rate = rate.replace('m', '');
} else if (rate.indexOf('m') == rate.length - 2) {
rate = rate.replace('mb', '');
}
new_obj[0]['Path'] = obj[0].path;
new_obj[0]['Rate'] = rate * 1024 * 1024;
return new_obj;
} else if (rate.includes('g')) {
if (rate.indexOf('g') == rate.length - 1) {
rate = rate.replace('g', '');
} else if (rate.indexOf('g') == rate.length - 2) {
rate = rate.replace('gb', '');
}
new_obj[0]['Path'] = obj[0].path;
new_obj[0]['Rate'] = rate * 1024 * 1024 * 1024;
return new_obj;
}
}
var buildEnvVarsFromFile = function (env_file_path, output) {
// Each line in an env file MUST be in `VAR=VAL` format.
try {
let env_file = fs.readFileSync(env_file_path, 'utf8').toString().split('\n');
for (let env_line of env_file) {
// Lines beginning with `#` MUST be ignored. Blank lines MUST also be ignored.
if (env_line != '' && env_line.indexOf('#') != 0) {
let env_line_split = env_line.split('=');
// `VAL` MAY be omitted, sin such cases the variable value is empty string. `=VAL` MAY be omitted, in such cases the variable is **unset**.
if (env_line_split[0] != '' && env_line_split[1] != '') {
output.push(env_line);
}
}
}
} catch (e) {
throw e;
}
}
var convertFancyDurationToMs = function (value) {
let interval = parseInt(value);
if (value == interval) {
return value;
} else if (value.includes('m') && value.includes('s')) {
let minutes = parseInt(value.substring(0, value.indexOf('m')));
let seconds = parseInt(value.substring(value.indexOf('m') + 1, value.indexOf('s')));
return ((minutes * 60) + seconds) * 1000 * 1000000;
} else {
return parseInt(value.substring(0, value.length - 2)) * 1000 * 1000000;
}
}
var fillPortArray = function (start, end) {
return Array(end - start + 1).fill().map((_, idx) => start + idx);
}
module.exports = {
'getImages': function (recipe) {
var images = [];
var serviceNames = Object.keys(recipe.services || []);
for (var serviceName of serviceNames) {
if (recipe.services[serviceName].image) {
images.push(recipe.services[serviceName].image);
}
}
return images;
},
'sortServices': function (recipe) {

@@ -9,3 +20,3 @@ var order = [];

if (order.indexOf(serviceName) === -1) {
insertService(serviceName, recipe.services[serviceName].depends_on || [], order)
insertService(serviceName, recipe.services[serviceName].depends_on || [], order);
}

@@ -21,3 +32,3 @@ }

if (i === 0) {
networksToAttachSorted.push(networksToAttach[i])
networksToAttachSorted.push(networksToAttach[i]);
} else {

@@ -39,3 +50,3 @@ let aux = 0;

}
return networksToAttachSorted
return networksToAttachSorted;
}

@@ -42,0 +53,0 @@ }

@@ -1,2 +0,2 @@

module.exports = async function(docker, projectName, recipe, output) {
module.exports = async function (docker, projectName, recipe, output) {
var volumes = [];

@@ -6,2 +6,3 @@ var volumeNames = Object.keys(recipe.volumes || []);

var volume = recipe.volumes[volumeName];
if (volume === null) volume = {};
if (volume.external === true) continue;

@@ -8,0 +9,0 @@ var opts = {

{
"name": "dockerode-compose",
"version": "1.1.0",
"version": "1.1.1",
"description": "docker-compose in nodejs using dockerode",

@@ -5,0 +5,0 @@ "main": "./compose.js",

@@ -9,3 +9,3 @@ # dockerode-compose

### ToDo:
* HostConfig (and other spec) needs to be finished.
* Finish compose spec
* User friendly functions (partial deploys, etc) needs to be implemented.

@@ -30,2 +30,3 @@

(async () => {
await compose.pull();
var state = await compose.up('./test/wordpress.yml', 'wordpress');

@@ -32,0 +33,0 @@ console.log(state);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc