mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 02:01:35 +00:00
Issue #410: Cleanup images before running an update, preserving the ones that will be used in the target state
We add an extra image/container cleanup before applying updates, allowing any unwanted images to be deleted. When doing this, we take care not to delete images that will be used when the target state is applied. This prevents the problem of stale images being stored while the update lock is set, potentially leaving the device out of space. Running the cleanup *before* applying the update ensures that only one target image is downloaded: if a stale one had been downloaded previously, it will be deleted before starting the update for the new one. This can have a slight impact on delta performance, since the delta is potentially done from an older (and more different) version of the app, but can have a big impact on storage usage, as not doing this would duplicate the required free storage space when the update lock is set. Change-Type: patch Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
parent
d9b421a574
commit
5412e766da
@ -700,6 +700,13 @@ application.update = update = (force, scheduled = false) ->
|
||||
utils.setConfig('name', local.name) if local.name != deviceName
|
||||
.then ->
|
||||
parseEnvAndFormatRemoteApps(local.apps, uuid, apiKey)
|
||||
.tap (remoteApps) ->
|
||||
# Before running the updates, try to clean up any images that aren't in use
|
||||
# and will not be used in the target state
|
||||
return if application.localMode
|
||||
dockerUtils.cleanupContainersAndImages(_.map(remoteApps, 'imageId'))
|
||||
.catch (err) ->
|
||||
console.log('Cleanup failed: ', err, err.stack)
|
||||
.then (remoteApps) ->
|
||||
localApps = formatLocalApps(apps)
|
||||
resourcesForUpdate = compareForUpdate(localApps, remoteApps)
|
||||
|
@ -142,7 +142,7 @@ do ->
|
||||
|
||||
supervisorTagPromise = normalizeRepoTag(config.supervisorImage)
|
||||
|
||||
exports.cleanupContainersAndImages = ->
|
||||
exports.cleanupContainersAndImages = (extraImagesToIgnore = []) ->
|
||||
Promise.using writeLockImages(), ->
|
||||
Promise.join(
|
||||
knex('image').select('repoTag')
|
||||
@ -159,19 +159,25 @@ do ->
|
||||
.map (image) ->
|
||||
image.NormalizedRepoTags = Promise.map(image.RepoTags, normalizeRepoTag)
|
||||
Promise.props(image)
|
||||
(locallyCreatedTags, apps, dependentApps, supervisorTag, images) ->
|
||||
Promise.map(extraImagesToIgnore, normalizeRepoTag)
|
||||
(locallyCreatedTags, apps, dependentApps, supervisorTag, images, normalizedExtraImages) ->
|
||||
imageTags = _.map(images, 'NormalizedRepoTags')
|
||||
supervisorTags = _.filter imageTags, (tags) ->
|
||||
_.includes(tags, supervisorTag)
|
||||
appTags = _.filter imageTags, (tags) ->
|
||||
_.some tags, (tag) ->
|
||||
_.includes(apps, tag) or _.includes(dependentApps, tag)
|
||||
extraTags = _.filter imageTags, (tags) ->
|
||||
_.some tags, (tag) ->
|
||||
_.includes(normalizedExtraImages, tag)
|
||||
supervisorTags = _.flatten(supervisorTags)
|
||||
appTags = _.flatten(appTags)
|
||||
extraTags = _.flatten(extraTags)
|
||||
locallyCreatedTags = _.flatten(locallyCreatedTags)
|
||||
return { images, supervisorTags, appTags, locallyCreatedTags }
|
||||
|
||||
return { images, supervisorTags, appTags, locallyCreatedTags, extraTags }
|
||||
)
|
||||
.then ({ images, supervisorTags, appTags, locallyCreatedTags }) ->
|
||||
.then ({ images, supervisorTags, appTags, locallyCreatedTags, extraTags }) ->
|
||||
# Cleanup containers first, so that they don't block image removal.
|
||||
docker.listContainersAsync(all: true)
|
||||
.filter (containerInfo) ->
|
||||
@ -182,6 +188,8 @@ do ->
|
||||
return false
|
||||
if _.includes(locallyCreatedTags, repoTag)
|
||||
return false
|
||||
if _.includes(extraTags, repoTag)
|
||||
return false
|
||||
if !_.includes(supervisorTags, repoTag)
|
||||
return true
|
||||
return containerHasExited(containerInfo.Id)
|
||||
@ -193,7 +201,7 @@ do ->
|
||||
.then ->
|
||||
imagesToClean = _.reject images, (image) ->
|
||||
_.some image.NormalizedRepoTags, (tag) ->
|
||||
return _.includes(appTags, tag) or _.includes(supervisorTags, tag) or _.includes(locallyCreatedTags, tag)
|
||||
return _.includes(appTags, tag) or _.includes(supervisorTags, tag) or _.includes(locallyCreatedTags, tag) or _.includes(extraTags, tag)
|
||||
Promise.map imagesToClean, (image) ->
|
||||
Promise.map image.RepoTags.concat(image.Id), (tag) ->
|
||||
docker.getImage(tag).removeAsync(force: true)
|
||||
|
Loading…
x
Reference in New Issue
Block a user