Class: DockerCleaner::Images

Inherits:
Object
  • Object
show all
Defined in:
lib/docker_cleaner/images.rb

Instance Method Summary collapse

Constructor Details

#initialize(registries, prefix, logger, opts = {}) ⇒ Images

Returns a new instance of Images.



3
4
5
6
7
8
9
# File 'lib/docker_cleaner/images.rb', line 3

def initialize registries, prefix, logger, opts = {}
  @prefix = prefix || ""
  @registries = registries
  @logger = logger
  @delay = opts.fetch(:delay, 0)
  @retention = Time.now.to_i - opts.fetch(:retention, 6) * 3600
end

Instance Method Details

#clean_old_imagesObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/docker_cleaner/images.rb', line 33

def clean_old_images
  apps = images_with_latest
  apps.each do |app, images|
    if app =~ /.*-tmax$/
      next
    end
    images.each do |i|
      unless i.info["Created"] == apps["#{app}-tmax"]
        @logger.info "Remove #{i.info['RepoTags'][0]} => #{i.id[0...10]}"
        begin
          i.remove
          sleep(@delay)
        rescue Docker::Error::NotFoundError
        rescue Docker::Error::ConflictError => e
          @logger.warn "Conflict when removing #{i.info['RepoTags'][0]} - ID: #{i.id[0...10]}"
          @logger.warn " !     #{e.message}"
        end
      end
    end
  end
end

#clean_unnamed_imagesObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/docker_cleaner/images.rb', line 17

def clean_unnamed_images
  Docker::Image.all.select do |image|
    image.info["RepoTags"].nil? || image.info["RepoTags"][0] == "<none>:<none>"
  end.each do |image|
    @logger.info "Remove unnamed image #{image.id[0...10]}"
    begin
      image.remove
      sleep(@delay)
    rescue Docker::Error::NotFoundError
    rescue Docker::Error::ConflictError => e
      @logger.warn "Conflict when removing #{image.id[0...10]}"
      @logger.warn " !     #{e.message}"
    end
  end
end

#clean_unused_imagesObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/docker_cleaner/images.rb', line 82

def clean_unused_images
  used_images = Docker::Container.all.map{|c| c.info["Image"]}.select{|i| registries_include?(i) }.uniq
  # Images older than 2 months
  images = Docker::Image.all.select{|i| i.info["RepoTags"] && registries_include?(i.info["RepoTags"][0]) && i.info["Created"] < @retention }
  image_repos = images.map{|i| i.info["RepoTags"][0]}
  unused_images = image_repos - used_images

  unused_images.each do |i|
    image = images.select{|docker_image| docker_image.info["RepoTags"][0] == i}[0]
    @logger.info "Remove unused image #{image.info['RepoTags'][0]} => #{image.id[0...10]}"
    begin
      image.remove
      sleep(@delay)
    rescue Docker::Error::NotFoundError
    rescue Docker::Error::ConflictError => e
      @logger.warn "Conflict when removing #{image.info['RepoTags'][0]} - ID: #{image.id[0...10]}"
      @logger.warn " !     #{e.message}"
    end
  end
end

#images_with_latestObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/docker_cleaner/images.rb', line 55

def images_with_latest
  images ||= Docker::Image.all
  apps = {}

  images.each do |i|
    # RepoTags can be nil sometimes, in this case we ignore the image
    next if i.info["RepoTags"].nil?
    if registries_include?(i.info["RepoTags"][0])
      name = i.info["RepoTags"][0].split(":")[0]
      tmax = "#{name}-tmax"

      if apps[name].nil?
        apps[name] = [i]
      else
        apps[name] << i
      end

      if apps[tmax].nil?
        apps[tmax] = i.info["Created"]
      elsif apps[tmax] < i.info["Created"]
        apps[tmax] = i.info["Created"]
      end
    end
  end
  apps
end

#runObject



11
12
13
14
15
# File 'lib/docker_cleaner/images.rb', line 11

def run
  clean_old_images
  clean_unnamed_images
  clean_unused_images
end