diff --git a/src/apptask.js b/src/apptask.js index 13c2454a7..998445728 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -138,6 +138,8 @@ function unconfigureNginx(app, callback) { function createContainer(app, callback) { assert(!app.containerId); // otherwise, it will trigger volumeFrom + debugApp(app, 'creating container'); + docker.createContainer(app, function (error, container) { if (error) return callback(new Error('Error creating container: ' + error)); @@ -145,8 +147,10 @@ function createContainer(app, callback) { }); } -function deleteContainer(app, callback) { - docker.deleteContainer(app.containerId, function (error) { +function deleteContainers(app, callback) { + debugApp(app, 'deleting containers'); + + docker.deleteContainers(app.id, function (error) { if (error) return callback(new Error('Error deleting container: ' + error)); updateApp(app, { containerId: null }, callback); @@ -341,7 +345,7 @@ function install(app, callback) { updateApp.bind(null, app, { installationProgress: '10, Cleaning up old install' }), removeCollectdProfile.bind(null, app), stopApp.bind(null, app), - deleteContainer.bind(null, app), + deleteContainers.bind(null, app), addons.teardownAddons.bind(null, app, app.manifest.addons), deleteVolume.bind(null, app), unregisterSubdomain.bind(null, app, app.location), @@ -427,7 +431,7 @@ function restore(app, callback) { updateApp.bind(null, app, { installationProgress: '10, Cleaning up old install' }), removeCollectdProfile.bind(null, app), stopApp.bind(null, app), - deleteContainer.bind(null, app), + deleteContainers.bind(null, app), // oldConfig can be null during upgrades addons.teardownAddons.bind(null, app, app.oldConfig ? app.oldConfig.manifest.addons : null), deleteVolume.bind(null, app), @@ -493,7 +497,7 @@ function configure(app, callback) { updateApp.bind(null, app, { installationProgress: '10, Cleaning up old install' }), removeCollectdProfile.bind(null, app), stopApp.bind(null, app), - deleteContainer.bind(null, app), + deleteContainers.bind(null, app), function (next) { // oldConfig can be null during an infra update if (!app.oldConfig || app.oldConfig.location === app.location) return next(); @@ -556,7 +560,7 @@ function update(app, callback) { updateApp.bind(null, app, { installationProgress: '10, Cleaning up old install' }), removeCollectdProfile.bind(null, app), stopApp.bind(null, app), - deleteContainer.bind(null, app), + deleteContainers.bind(null, app), addons.teardownAddons.bind(null, app, unusedAddons), function deleteImageIfChanged(done) { if (app.oldConfig.manifest.dockerImage === app.manifest.dockerImage) return done(); @@ -616,7 +620,7 @@ function uninstall(app, callback) { stopApp.bind(null, app), updateApp.bind(null, app, { installationProgress: '20, Deleting container' }), - deleteContainer.bind(null, app), + deleteContainers.bind(null, app), updateApp.bind(null, app, { installationProgress: '30, Teardown addons' }), addons.teardownAddons.bind(null, app, app.manifest.addons), diff --git a/src/docker.js b/src/docker.js index 9287e1bda..ea60efbf4 100644 --- a/src/docker.js +++ b/src/docker.js @@ -17,7 +17,8 @@ exports = module.exports = { startContainer: startContainer, stopContainer: stopContainer, deleteContainer: deleteContainer, - deleteImage: deleteImage + deleteImage: deleteImage, + deleteContainers: deleteContainers }; function connectionInstance() { @@ -251,6 +252,8 @@ function deleteContainer(containerId, callback) { assert(!containerId || typeof containerId === 'string'); assert.strictEqual(typeof callback, 'function'); + debug('deleting container %s', containerId); + if (containerId === null) return callback(null); var docker = exports.connection; @@ -270,6 +273,23 @@ function deleteContainer(containerId, callback) { }); } +function deleteContainers(appId, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof callback, 'function'); + + var docker = exports.connection; + + debug('deleting containers of %s', appId); + + docker.listContainers({ all: 1, filters: JSON.stringify({ label: [ 'appId=' + appId ] }) }, function (error, containers) { + if (error) return callback(error); + + async.eachSeries(containers, function (container, iteratorDone) { + deleteContainer(container.Id, iteratorDone); + }, callback); + }); +} + function deleteImage(manifest, callback) { assert(!manifest || typeof manifest === 'object'); assert.strictEqual(typeof callback, 'function');