Class: Dockly::Docker

Inherits:
Object
  • Object
show all
Includes:
Util::DSL, Util::Logger::Mixin
Defined in:
lib/dockly/docker.rb

Defined Under Namespace

Classes: Registry

Instance Method Summary collapse

Instance Method Details

#add_git_archive(image) ⇒ Object



125
126
127
128
129
130
131
132
# File 'lib/dockly/docker.rb', line 125

def add_git_archive(image)
  return image if git_archive.nil?

  image.insert_local(
    'localPath' => git_archive_tar,
    'outputPath' => '/'
  )
end

#build_image(image) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/dockly/docker.rb', line 134

def build_image(image)
  ensure_present! :name, :build
  info "starting build from #{image.id}"
  out_image = ::Docker::Image.build("from #{image.id}\n#{build}")
  info "built the image: #{out_image.id}"
  out_image.tag(:repo => repo, :tag => tag)
  out_image
end

#cleanup(images) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/dockly/docker.rb', line 51

def cleanup(images)
  ::Docker::Container.all(:all => true).each do |container|
    image_id = container.json['Image']
    if images.any? { |image| image.id.start_with?(image_id) || image_id.start_with?(image.id) }
      container.kill
      container.delete
    end
  end
  images.each { |image| image.remove rescue nil }
end

#ensure_tar(file_name) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/dockly/docker.rb', line 80

def ensure_tar(file_name)
  if Dockly::Util::Tar.is_tar?(file_name)
    file_name
  elsif Dockly::Util::Tar.is_gzip?(file_name)
    file_name
  else
    raise "Expected a (possibly gzipped) tar: #{file_name}"
  end
end

#export_filenameObject



62
63
64
# File 'lib/dockly/docker.rb', line 62

def export_filename
  "#{name}-image.tgz"
end

#export_image(image) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/dockly/docker.rb', line 154

def export_image(image)
  ensure_present! :name
  if registry.nil?
    ensure_present! :build_dir
    container = ::Docker::Container.create('Image' => image.id, 'Cmd' => %w[true])
    info "created the container: #{container.id}"
    Zlib::GzipWriter.open(tar_path) do |file|
      container.export do |chunk, remaining, total|
        file.write(chunk)
      end
    end
    info "done writing the docker tar: #{export_filename}"
  else
    push_to_registry(image)
  end
end

#fetch_importObject



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/dockly/docker.rb', line 182

def fetch_import
  ensure_present! :import
  path = "/tmp/dockly-docker-import.#{name}.#{File.basename(import)}"

  if File.exist?(path)
    debug "already fetched #{import}"
  else
    debug "fetching #{import}"
    File.open("#{path}.tmp", 'wb') do |file|
      case import
        when /^s3:\/\/(?<bucket_name>.+?)\/(?<object_path>.+)$/
          connection.get_object(Regexp.last_match[:bucket_name],
                                Regexp.last_match[:object_path]) do |chunk, remaining, total|
            file.write(chunk)
          end
        when /^https?:\/\//
          Excon.get(import, :response_block => lambda { |chunk, remaining, total|
            file.write(chunk)
          })
        else
          raise "You can only import from S3 or a public url"
      end
    end
    FileUtils.mv("#{path}.tmp", path, :force => true)
  end
  path
end

#generate!Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/dockly/docker.rb', line 28

def generate!
  Docker.options = { :read_timeout => timeout, :write_timeout => timeout }
  images = {}

  if registry_import.nil?
    docker_tar = File.absolute_path(ensure_tar(fetch_import))
    images[:one] = import_base(docker_tar)
  else
    registry.authenticate! unless registry.nil?
    images[:one] = ::Docker::Image.create('fromImage' => registry_import)
  end

  images[:two] = add_git_archive(images[:one])
  images[:three] = run_build_caches(images[:two])
  images[:four] = build_image(images[:three])

  export_image(images[:four])

  true
ensure
  cleanup(images.values.compact) if cleanup_images
end

#git_archive_dirObject



106
107
108
# File 'lib/dockly/docker.rb', line 106

def git_archive_dir
  @git_archive_dir ||= File.join(build_dir, "gitarc")
end

#git_archive_pathObject



110
111
112
# File 'lib/dockly/docker.rb', line 110

def git_archive_path
  "#{git_archive_dir}/#{name}.tar"
end

#git_archive_tarObject



114
115
116
# File 'lib/dockly/docker.rb', line 114

def git_archive_tar
  git_archive && File.absolute_path(make_git_archive)
end

#import_base(docker_tar) ⇒ Object



118
119
120
121
122
123
# File 'lib/dockly/docker.rb', line 118

def import_base(docker_tar)
  info "importing the docker image from #{docker_tar}"
  image = ::Docker::Image.import(docker_tar)
  info "imported docker image: #{image.id}"
  image
end

#make_git_archiveObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/dockly/docker.rb', line 90

def make_git_archive
  ensure_present! :git_archive
  info "initializing"

  prefix = git_archive
  prefix += '/' unless prefix.end_with?('/')

  FileUtils.rm_rf(git_archive_dir)
  FileUtils.mkdir_p(git_archive_dir)
  info "archiving #{Dockly::Util::Git.git_sha}"
  Grit::Git.with_timeout(120) do
    Dockly::Util::Git.git_repo.archive_to_file(Dockly::Util::Git.git_sha, prefix, git_archive_path, 'tar', 'cat')
  end
  git_archive_path
end

#push_to_registry(image) ⇒ Object



171
172
173
174
175
176
177
178
179
180
# File 'lib/dockly/docker.rb', line 171

def push_to_registry(image)
  ensure_present! :registry
  info "Exporting #{image.id} to Docker registry at #{registry.server_address}"
  registry.authenticate!
  image = Docker::Image.all(:all => true).find { |img|
    img.id.start_with?(image.id) || image.id.start_with?(img.id)
  }
  raise "Could not find image after authentication" if image.nil?
  image.push(registry.to_h, :registry => registry.server_address)
end

#repoObject



143
144
145
146
147
148
149
150
151
152
# File 'lib/dockly/docker.rb', line 143

def repo
  @repo ||= case
  when registry.nil?
    name
  when registry.default_server_address?
    "#{registry.username}/#{name}"
  else
    "#{registry.server_address}/#{name}"
  end
end

#repository(value = nil) ⇒ Object



210
211
212
# File 'lib/dockly/docker.rb', line 210

def repository(value = nil)
  name(value)
end

#run_build_caches(image) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/dockly/docker.rb', line 66

def run_build_caches(image)
  info "starting build caches"
  (build_cache || []).each do |cache|
    cache.image = image
    image = cache.execute!
  end
  info "finished build caches"
  image
end

#tar_pathObject



76
77
78
# File 'lib/dockly/docker.rb', line 76

def tar_path
  File.join(build_dir, export_filename)
end