Class: Docker::Image

Inherits:
Object
  • Object
show all
Includes:
Base
Defined in:
lib/docker/image.rb

Overview

This class represents a Docker Image.

Instance Attribute Summary

Attributes included from Base

#connection, #id, #info

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Base

#initialize, #normalize_hash

Class Method Details

.all(opts = {}, conn = Docker.connection) ⇒ Object

Return every Image.



171
172
173
174
# File 'lib/docker/image.rb', line 171

def all(opts = {}, conn = Docker.connection)
  hashes = Docker::Util.parse_json(conn.get('/images/json', opts)) || []
  hashes.map { |hash| new(conn, hash) }
end

.build(commands, opts = {}, connection = Docker.connection, &block) ⇒ Object

Given a Dockerfile as a string, builds an Image.



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/docker/image.rb', line 208

def build(commands, opts = {}, connection = Docker.connection, &block)
  body = ""
  connection.post(
    '/build', opts,
    :body => Docker::Util.create_tar('Dockerfile' => commands),
    :response_block => response_block(body, &block)
  )
  new(connection, 'id' => Docker::Util.extract_id(body))
rescue Docker::Error::ServerError
  raise Docker::Error::UnexpectedResponseError
end

.build_from_dir(dir, opts = {}, connection = Docker.connection, creds = nil, &block) ⇒ Object

Given a directory that contains a Dockerfile, builds an Image.

If a block is passed, chunks of output produced by Docker will be passed to that block.



246
247
248
249
250
251
252
253
254
255
256
# File 'lib/docker/image.rb', line 246

def build_from_dir(dir, opts = {}, connection = Docker.connection,
                   creds = nil, &block)

  tar = Docker::Util.create_dir_tar(dir)
  build_from_tar tar, opts, connection, creds, &block
ensure
  unless tar.nil?
    tar.close
    FileUtils.rm(tar.path, force: true)
  end
end

.build_from_tar(tar, opts = {}, connection = Docker.connection, creds = nil, &block) ⇒ Object

Given File like object containing a tar file, builds an Image.

If a block is passed, chunks of output produced by Docker will be passed to that block.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/docker/image.rb', line 224

def build_from_tar(tar, opts = {}, connection = Docker.connection,
                   creds = nil, &block)

  headers = build_headers(creds)

  # The response_block passed to Excon will build up this body variable.
  body = ""
  connection.post(
    '/build', opts,
    :headers => headers,
    :response_block => response_block(body, &block)
  ) { tar.read(Excon.defaults[:chunk_size]).to_s }

  new(connection,
      'id' => Docker::Util.extract_id(body),
      :headers => headers)
end

.create(opts = {}, creds = nil, conn = Docker.connection, &block) ⇒ Object

Create a new Image.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/docker/image.rb', line 105

def create(opts = {}, creds = nil, conn = Docker.connection, &block)
  credentials = creds.nil? ? Docker.creds : creds.to_json
  headers = credentials && Docker::Util.build_auth_header(credentials) || {}
  body = ''
  conn.post(
    '/images/create',
    opts,
    :headers => headers,
    :response_block => response_block(body, &block)
  )
  json = Docker::Util.fix_json(body)
  completions = json.compact.select { |j| j['status'] && j['status'].include?('complete') }
  if image = completions.reverse_each.find { |j| j['id'] }
    get(image['id'], {}, conn)
  elsif image = opts['fromImage'] || opts[:fromImage]
    get(image, {}, conn)
  end
end

.exist?(id, opts = {}, conn = Docker.connection) ⇒ Boolean

Check if an image exists.

Returns:

  • (Boolean)


163
164
165
166
167
168
# File 'lib/docker/image.rb', line 163

def exist?(id, opts = {}, conn = Docker.connection)
  get(id, opts, conn)
  true
rescue Docker::Error::NotFoundError
  false
end

.get(id, opts = {}, conn = Docker.connection) ⇒ Object

Return a specific image.



125
126
127
128
129
# File 'lib/docker/image.rb', line 125

def get(id, opts = {}, conn = Docker.connection)
  image_json = conn.get("/images/#{URI.encode(id)}/json", opts)
  hash = Docker::Util.parse_json(image_json) || {}
  new(conn, hash)
end

.import(imp, opts = {}, conn = Docker.connection) ⇒ Object

Import an Image from the output of Docker::Container#export. The first argument may either be a File or URI.



186
187
188
189
190
191
192
193
194
# File 'lib/docker/image.rb', line 186

def import(imp, opts = {}, conn = Docker.connection)
  open(imp) do |io|
    import_stream(opts, conn) do
      io.read(Excon.defaults[:chunk_size]).to_s
    end
  end
rescue StandardError
  raise Docker::Error::IOError, "Could not import '#{imp}'"
end

.import_stream(options = {}, connection = Docker.connection, &block) ⇒ Object



196
197
198
199
200
201
202
203
204
205
# File 'lib/docker/image.rb', line 196

def import_stream(options = {}, connection = Docker.connection, &block)
  body = connection.post(
    '/images/create',
     options.merge('fromSrc' => '-'),
     :headers => { 'Content-Type' => 'application/tar',
                   'Transfer-Encoding' => 'chunked' },
     &block
  )
  new(connection, 'id'=> Docker::Util.parse_json(body)['status'])
end

.save(names, filename = nil, conn = Docker.connection) ⇒ NilClass, String

Save the raw binary representation or one or more Docker images

representation of the binary data. If the filename is not nil, then return nil.

Parameters:

  • names (String, Array#String)

    The image(s) you wish to save

  • filename (String) (defaults to: nil)

    The file to export the data to.

  • conn (Docker::Connection) (defaults to: Docker.connection)

    The Docker connection to use

Returns:

  • (NilClass, String)

    If filename is nil, return the string



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/docker/image.rb', line 140

def save(names, filename = nil, conn = Docker.connection)
  # By using compare_by_identity we can create a Hash that has
  # the same key multiple times.
  query = {}
  query.compare_by_identity
  Array(names).each do |name|
    query['names'.dup] = URI.encode(name)
  end

  if filename
    file = File.open(filename, 'wb')
    conn.get(
      '/images/get', query,
      :response_block => response_block_for_save(file)
    )
    file.close
    nil
  else
    conn.get('/images/get', query)
  end
end

.search(query = {}, connection = Docker.connection) ⇒ Object

Given a query like ‘{ :term => ’sshd’ }‘, queries the Docker Registry for a corresponding Image.



178
179
180
181
182
# File 'lib/docker/image.rb', line 178

def search(query = {}, connection = Docker.connection)
  body = connection.get('/images/search', query)
  hashes = Docker::Util.parse_json(body) || []
  hashes.map { |hash| new(connection, 'id' => hash['name']) }
end

Instance Method Details

#insert_local(opts = {}) ⇒ Object

Given a path of a local file and the path it should be inserted, creates a new Image that has that file.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/docker/image.rb', line 51

def insert_local(opts = {})
  local_paths = opts.delete('localPath')
  output_path = opts.delete('outputPath')

  local_paths = [ local_paths ] unless local_paths.is_a?(Array)

  file_hash = Docker::Util.file_hash_from_paths(local_paths)

  file_hash['Dockerfile'] = dockerfile_for(file_hash, output_path)

  tar = Docker::Util.create_tar(file_hash)
  body = connection.post('/build', opts, :body => tar)
  self.class.send(:new, connection, 'id' => Docker::Util.extract_id(body))
end

#push(creds = nil, options = {}, &block) ⇒ Object

Push the Image to the Docker registry.

Raises:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/docker/image.rb', line 25

def push(creds = nil, options = {}, &block)
  repo_tag = options.delete(:repo_tag) || ensure_repo_tags.first
  raise ArgumentError, "Image is untagged" if repo_tag.nil?
  repo, tag = Docker::Util.parse_repo_tag(repo_tag)
  raise ArgumentError, "Image does not have a name to push." if repo.nil?

  body = ""
  credentials = creds || Docker.creds || {}
  headers = Docker::Util.build_auth_header(credentials)
  opts = {:tag => tag}.merge(options)
  connection.post("/images/#{repo}/push", opts, :headers => headers,
                  :response_block => self.class.response_block(body, &block))
  self
end

#refresh!Object

Update the @info hash, which is the only mutable state in this object.



93
94
95
96
97
98
99
100
# File 'lib/docker/image.rb', line 93

def refresh!
  img = Docker::Image.all({:all => true}, connection).find { |image|
    image.id.start_with?(self.id) || self.id.start_with?(image.id)
  }
  info.merge!(self.json)
  img && info.merge!(img.info)
  self
end

#remove(opts = {}) ⇒ Object Also known as: delete

Remove the Image from the server.



67
68
69
70
# File 'lib/docker/image.rb', line 67

def remove(opts = {})
  name = opts.delete(:name) || self.id
  connection.delete("/images/#{name}", opts)
end

#run(cmd = nil) ⇒ Object

Given a command and optional list of streams to attach to, run a command on an Image. This will not modify the Image, but rather create a new Container to run the Image. If the image has an embedded config, no command is necessary, but it will fail with 500 if no config is saved with the image



9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/docker/image.rb', line 9

def run(cmd=nil)
  opts = { 'Image' => self.id }
  opts["Cmd"] = cmd.is_a?(String) ? cmd.split(/\s+/) : cmd
  begin
    Docker::Container.create(opts, connection)
                     .tap(&:start!)
  rescue ServerError => ex
    if cmd
      raise ex
    else
      raise ServerError, "No command specified."
    end
  end
end

#save(filename = nil) ⇒ Object

Save the image as a tarball



88
89
90
# File 'lib/docker/image.rb', line 88

def save(filename = nil)
  self.class.save(self.id, filename, connection)
end

#tag(opts = {}) ⇒ Object

Tag the Image.



41
42
43
44
45
46
47
# File 'lib/docker/image.rb', line 41

def tag(opts = {})
  self.info['RepoTags'] ||= []
  connection.post(path_for(:tag), opts)
  repo = opts['repo'] || opts[:repo]
  tag = opts['tag'] || opts[:tag] || 'latest'
  self.info['RepoTags'] << "#{repo}:#{tag}"
end

#to_sObject

Return a String representation of the Image.



74
75
76
77
# File 'lib/docker/image.rb', line 74

def to_s
  "Docker::Image { :id => #{self.id}, :info => #{self.info.inspect}, "\
    ":connection => #{self.connection} }"
end