Skip to content

Instantly share code, notes, and snippets.

@marcbachmann
Created December 22, 2016 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcbachmann/02a46c43eaea853cba9d1fde31544f15 to your computer and use it in GitHub Desktop.
Save marcbachmann/02a46c43eaea853cba9d1fde31544f15 to your computer and use it in GitHub Desktop.
var async = require('async')
var ms = require('ms')
var _ = require('lodash')
var config = require('./config')
var Docker = require('dockerode')
var docker = new Docker(config.docker)
var api
api =
module.exports = {
pull: function (name, callback) {
docker.pull(name, function(err, stream) {
if (err) return callback(err)
docker.modem.followProgress(stream, onFinished)
function onFinished(err, output) {
if (err) return callback(err)
callback(null, output)
}
})
},
run: function (opts, callback) {
var ttl = opts.ttl || '7 days'
if (typeof ttl === 'string') ttl = ms(ttl)
var labels = {
createdByDeployer: 'true',
stack: opts.stack,
type: opts.type,
deleteAfter: new Date(Date.now() + ttl).toISOString(),
}
docker.createContainer({
Image: opts.image,
Labels: labels
}, function (err, container) {
if (err) return callback(err)
container.start(function(err, data) {
if (err) return callback(err)
callback(null, arguments)
})
})
},
build: {
// Let docker host fetch the remote url
fromRemote: function (opts, callback) {
docker.buildImage(null, {remote: opts.repository, t: opts.name}, callback)
},
fromTar: function (opts, callback) {
}
},
listContainers: function (opts, callback) {
if (arguments.length == 1) callback = opts
if (opts && opts.stack) {
docker.listContainers({all: true}, function (err, containers) {
if (err) return callback(err)
var isStack = function (container) { return container.Labels && container.Labels.stack == opts.stack }
containers = _.filter(containers, isStack)
callback(null, containers)
})
}
else {
docker.listContainers({all: true}, callback)
}
},
removeStack: function (stackId, callback) {
api.listContainers({stack: stackId}, function (err, containers) {
if (err) return callback(err)
async.each(containers, function (c, done) {
docker.getContainer(c.Id).remove({force: true}, done)
}, function (err) {
if (err) return callback(err)
callback(null, {
totalRemoved: containers.length,
removedContainers: containers
})
})
})
},
// Clean containers
// TODO MB: Also remove unused images
clean: function (opts, callback) {
if (arguments.length == 1) callback = opts
api.listContainers(function (err, containers) {
if (err) return callback(err)
var currentTime = Date.now()
var containersToRemove = opts.force? filterDeployerServices(containers) : filterExpiredContainers(containers)
var stacksToRemove = _.unique(_.pluck(containersToRemove, 'Labels.stack'))
async.map(stacksToRemove, function (stack, done) {
api.removeStack(stack, done)
}, function (err, res) {
if (err) return callback(err)
var containers = _.flatten(_.pluck(res, 'removedContainers'))
var total = _.reduce(_.pluck(res, 'totalRemoved'), function(t, n) { return t + n })
callback(null, {
totalRemoved: total,
removedContainers: containers
})
})
})
}
}
function filterExpiredContainers (containers) {
_.filter(containers, function (container) {
// Filter containers that aren't from this service
if (_.isEmpty(container.Labels)) return false
if (!container.Labels.createdByDeployer) return false
var destroyAfter = new Date(container.Labels.destroyAfter)
if (destroyAfter && destroyAfter.getTime() < currentTime) return true
if (_.contains(container.Status, 'Exited')) return true
// Containers with the status 'Created' currently don't get removed
return false
})
}
function filterDeployerServices (containers) {
_.filter(containers, function (container) {
// Filter containers that aren't from this service
if (_.isEmpty(container.Labels)) return false
if (!container.Labels.createdByDeployer) return false
return true
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment