Skip to content

Commit 148fb47

Browse files
userleruedajaileon
andcommitted
Add option to simulate docker-compose down
- Adds option for down - Adds option to add labels for volumes, networks and services so it can be properly identified by Docker Desktop Co-Authored-By: Jairo Leon <[email protected]>
1 parent c21335f commit 148fb47

File tree

9 files changed

+480
-185
lines changed

9 files changed

+480
-185
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,4 @@ dist
104104

105105
# TernJS port file
106106
.tern-port
107+
.DS_Store

.prettierrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"singleQuote": true
3+
}

compose.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,32 @@ class Compose {
2727
}
2828
}
2929

30+
async down(options) {
31+
var output = {};
32+
try {
33+
output.file = this.file;
34+
output.services = await services.down(this.docker, this.projectName, this.recipe, output, options);
35+
output.networks = await networks.down(this.docker, this.projectName, this.recipe, output);
36+
if (options !== undefined) {
37+
if (options.volumes) {
38+
output.volumes = await volumes.down(this.docker, this.projectName, this.recipe, output);
39+
}
40+
}
41+
return output;
42+
} catch (e) {
43+
throw e;
44+
}
45+
}
46+
3047
async up(options) {
3148
var output = {};
3249
try {
3350
output.file = this.file;
3451
output.secrets = await secrets(this.docker, this.projectName, this.recipe, output);
35-
output.volumes = await volumes(this.docker, this.projectName, this.recipe, output);
52+
output.volumes = await volumes.up(this.docker, this.projectName, this.recipe, output);
3653
output.configs = await configs(this.docker, this.projectName, this.recipe, output);
37-
output.networks = await networks(this.docker, this.projectName, this.recipe, output);
38-
output.services = await services(this.docker, this.projectName, this.recipe, output, options);
54+
output.networks = await networks.up(this.docker, this.projectName, this.recipe, output);
55+
output.services = await services.up(this.docker, this.projectName, this.recipe, output, options);
3956
return output;
4057
} catch (e) {
4158
throw e;

examples/down.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
var Dockerode = require('dockerode');
2+
var DockerodeCompose = require('../compose');
3+
4+
var docker = new Dockerode();
5+
var compose = new DockerodeCompose(
6+
docker,
7+
'./test/assets/wordpress_original.yml',
8+
'wordpress'
9+
);
10+
11+
(async () => {
12+
var state = await compose.down({ volumes: true });
13+
console.log(state);
14+
})();

lib/networks.js

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,121 @@
1-
module.exports = async function (docker, projectName, recipe, output) {
1+
async function down(docker, projectName, recipe) {
2+
var networks = [];
3+
var networkNames = Object.keys(recipe.networks || { default: null });
4+
for (var networkName of networkNames) {
5+
try {
6+
var network = await docker.getNetwork(projectName + '_' + networkName);
7+
} catch (e) {}
8+
9+
try {
10+
await network.remove();
11+
} catch (e) {}
12+
}
13+
return networks;
14+
}
15+
16+
async function up(docker, projectName, recipe, output) {
217
var networks = [];
318
var networkNames = Object.keys(recipe.networks || []);
419
for (var networkName of networkNames) {
520
var network = recipe.networks[networkName];
621
if (network === null) {
722
try {
8-
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.createNetwork({ 'Name': projectName + '_' + networkName, 'CheckDuplicate': true }) });
23+
networks.push({
24+
name: projectName + '_' + networkName,
25+
network: await docker.createNetwork({
26+
Name: projectName + '_' + networkName,
27+
CheckDuplicate: true,
28+
}),
29+
});
930
} catch (err) {
10-
if (err.statusCode == 409 && err.json.message.includes('already exists')) {
11-
let returnedNetwork = await docker.listNetworks({ 'filters': { 'name': [projectName + '_' + networkName] } });
12-
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.getNetwork(returnedNetwork[0].Id) });
31+
if (
32+
err.statusCode == 409 &&
33+
err.json.message.includes('already exists')
34+
) {
35+
let returnedNetwork = await docker.listNetworks({
36+
filters: { name: [projectName + '_' + networkName] },
37+
});
38+
networks.push({
39+
name: projectName + '_' + networkName,
40+
network: await docker.getNetwork(returnedNetwork[0].Id),
41+
});
1342
} else {
1443
throw err;
1544
}
1645
}
17-
continue
46+
continue;
1847
}
1948
if (network.external === true) continue;
2049
var opts = {
21-
'Name': projectName + '_' + networkName,
22-
'Driver': network.driver,
23-
'DriverOpts': network.driver_opts,
24-
'Labels': network.labels,
25-
'Attachable': network.attachable,
26-
'EnableIPv6': network.enable_ipv6,
27-
'Internal': network.internal,
28-
'CheckDuplicate': true
50+
Name: projectName + '_' + networkName,
51+
Driver: network.driver,
52+
DriverOpts: network.driver_opts,
53+
Labels: {
54+
...network.labels,
55+
...{
56+
'com.docker.compose.network': 'default',
57+
'com.docker.compose.project': projectName,
58+
},
59+
},
60+
Attachable: network.attachable,
61+
EnableIPv6: network.enable_ipv6,
62+
Internal: network.internal,
63+
CheckDuplicate: true,
2964
};
3065
if (network.name !== undefined) {
3166
opts.Name = networkName;
3267
}
3368
if (network.ipam !== undefined) {
3469
opts.IPAM = {
35-
'Driver': network.ipam.driver,
36-
'Options': network.ipam.options
70+
Driver: network.ipam.driver,
71+
Options: network.ipam.options,
3772
};
3873
if (network.ipam.config !== undefined) {
3974
opts.IPAM['Config'] = {
40-
'Subnet': network.ipam.config.subnet,
41-
'IPRange': network.ipam.config.ip_range,
42-
'Gateway': network.ipam.config.gateway,
43-
'AuxAddress': network.ipam.config.aux_addresses
75+
Subnet: network.ipam.config.subnet,
76+
IPRange: network.ipam.config.ip_range,
77+
Gateway: network.ipam.config.gateway,
78+
AuxAddress: network.ipam.config.aux_addresses,
4479
};
4580
}
4681
}
4782
//if exists we have to compare with the existing network
48-
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.createNetwork(opts) });
83+
networks.push({
84+
name: projectName + '_' + networkName,
85+
network: await docker.createNetwork(opts),
86+
});
4987
}
5088

5189
if (networks.length === 0) {
5290
try {
53-
networks.push({ 'name': projectName + '_default', 'network': await docker.createNetwork({ 'Name': projectName + '_default', 'CheckDuplicate': true }) });
91+
networks.push({
92+
name: projectName + '_default',
93+
network: await docker.createNetwork({
94+
Name: projectName + '_default',
95+
CheckDuplicate: true,
96+
}),
97+
});
5498
} catch (err) {
55-
if (err.statusCode == 409 && err.json.message.includes('already exists')) {
56-
let returnedNetwork = await docker.listNetworks({ 'filters': { 'name': [projectName + '_default'] } });
57-
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.getNetwork(returnedNetwork[0].Id) });
99+
if (
100+
err.statusCode == 409 &&
101+
err.json.message.includes('already exists')
102+
) {
103+
let returnedNetwork = await docker.listNetworks({
104+
filters: { name: [projectName + '_default'] },
105+
});
106+
networks.push({
107+
name: projectName + '_' + networkName,
108+
network: await docker.getNetwork(returnedNetwork[0].Id),
109+
});
58110
} else {
59111
throw err;
60112
}
61113
}
62114
}
63115
return networks;
64116
}
117+
118+
module.exports = {
119+
down,
120+
up,
121+
};

0 commit comments

Comments
 (0)