Refactor container cleanup to remove all spurious containers

We change the way container cleanup works so that it compares running
app containers with the container names for the known apps. This allows
the cleanup to effectively delete any spurious/duplicated app containers.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
Pablo Carranza Velez 2017-10-17 17:53:56 -07:00
parent bd34a19a79
commit 0bc23df8c9

View File

@ -138,34 +138,33 @@ do ->
Promise.using writeLockImages(), -> Promise.using writeLockImages(), ->
Promise.join( Promise.join(
knex('app').select() knex('app').select()
.map ({ imageId }) -> .map (app) ->
normalizeRepoTag(imageId) app.imageId = normalizeRepoTag(app.imageId)
return Promise.props(app)
knex('dependentApp').select().whereNotNull('imageId') knex('dependentApp').select().whereNotNull('imageId')
.map ({ imageId }) -> .map ({ imageId }) ->
normalizeRepoTag(imageId) return normalizeRepoTag(imageId)
supervisorTagPromise supervisorTagPromise
docker.listImages() docker.listImages()
.map (image) -> .map (image) ->
image.NormalizedRepoTags = Promise.map(image.RepoTags, normalizeRepoTag) image.NormalizedRepoTags = Promise.map(image.RepoTags, normalizeRepoTag)
Promise.props(image) return Promise.props(image)
Promise.map(extraImagesToIgnore, normalizeRepoTag) Promise.map(extraImagesToIgnore, normalizeRepoTag)
(apps, dependentApps, supervisorTag, images, normalizedExtraImages) -> (apps, dependentApps, supervisorTag, images, normalizedExtraImages) ->
appNames = _.map(apps, 'containerName')
appImages = _.map(apps, 'imageId')
imageTags = _.map(images, 'NormalizedRepoTags') imageTags = _.map(images, 'NormalizedRepoTags')
supervisorTags = _.filter imageTags, (tags) ->
_.includes(tags, supervisorTag)
appTags = _.filter imageTags, (tags) -> appTags = _.filter imageTags, (tags) ->
_.some tags, (tag) -> _.some tags, (tag) ->
_.includes(apps, tag) or _.includes(dependentApps, tag) _.includes(appImages, tag) or _.includes(dependentApps, tag)
extraTags = _.filter imageTags, (tags) ->
_.some tags, (tag) ->
_.includes(normalizedExtraImages, tag)
supervisorTags = _.flatten(supervisorTags)
appTags = _.flatten(appTags) appTags = _.flatten(appTags)
supervisorTags = _.filter imageTags, (tags) ->
_.includes(tags, supervisorTag)
supervisorTags = _.flatten(supervisorTags)
extraTags = _.filter imageTags, (tags) ->
_.some(tags, (tag) -> _.includes(normalizedExtraImages, tag))
extraTags = _.flatten(extraTags) extraTags = _.flatten(extraTags)
allProtectedTags = _.union(appTags, supervisorTags, extraTags)
return { images, supervisorTags, appTags, extraTags }
)
.then ({ images, supervisorTags, appTags, extraTags }) ->
# Cleanup containers first, so that they don't block image removal. # Cleanup containers first, so that they don't block image removal.
docker.listContainers(all: true) docker.listContainers(all: true)
.filter (containerInfo) -> .filter (containerInfo) ->
@ -173,12 +172,11 @@ do ->
normalizeRepoTag(containerInfo.Image) normalizeRepoTag(containerInfo.Image)
.then (repoTag) -> .then (repoTag) ->
if _.includes(appTags, repoTag) if _.includes(appTags, repoTag)
return false return !_.some containerInfo.Names, (name) ->
if _.includes(extraTags, repoTag) _.some appNames, (appContainerName) -> "/#{appContainerName}" == name
return false if _.includes(supervisorTags, repoTag)
if !_.includes(supervisorTags, repoTag)
return true
return containerHasExited(containerInfo.Id) return containerHasExited(containerInfo.Id)
return true
.map (containerInfo) -> .map (containerInfo) ->
docker.getContainer(containerInfo.Id).remove(v: true, force: true) docker.getContainer(containerInfo.Id).remove(v: true, force: true)
.then -> .then ->
@ -186,14 +184,14 @@ do ->
.catch(_.noop) .catch(_.noop)
.then -> .then ->
imagesToClean = _.reject images, (image) -> imagesToClean = _.reject images, (image) ->
_.some image.NormalizedRepoTags, (tag) -> _.some(image.NormalizedRepoTags, (tag) -> _.includes(allProtectedTags, tag))
return _.includes(appTags, tag) or _.includes(supervisorTags, tag) or _.includes(extraTags, tag)
Promise.map imagesToClean, (image) -> Promise.map imagesToClean, (image) ->
Promise.map image.RepoTags.concat(image.Id), (tag) -> Promise.map image.RepoTags.concat(image.Id), (tag) ->
docker.getImage(tag).remove(force: true) docker.getImage(tag).remove(force: true)
.then -> .then ->
console.log('Deleted image:', tag, image.Id, image.RepoTags) console.log('Deleted image:', tag, image.Id, image.RepoTags)
.catch(_.noop) .catch(_.noop)
)
containerHasExited = (id) -> containerHasExited = (id) ->
docker.getContainer(id).inspect() docker.getContainer(id).inspect()