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.



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

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.



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/docker/image.rb', line 151

def build(commands, opts = {}, connection = Docker.connection, &block)
  body = ""
  connection.post(
    '/build', opts,
    :body => Docker::Util.create_tar('Dockerfile' => commands),
    :response_block => response_block_for_build(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.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/docker/image.rb', line 167

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

  tar = Docker::Util.create_dir_tar(dir)

  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_for_build(body, &block)
  ) { tar.read(Excon.defaults[:chunk_size]).to_s }

  new(connection,
      'id' => Docker::Util.extract_id(body),
      :headers => headers)
ensure
  unless tar.nil?
    tar.close
    FileUtils.rm(tar.path, force: true)
  end
end

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

Create a new Image.



97
98
99
100
101
102
103
104
# File 'lib/docker/image.rb', line 97

def create(opts = {}, creds = nil, conn = Docker.connection)
  credentials = creds.nil? ? Docker.creds : creds.to_json
  headers = !credentials.nil? && Docker::Util.build_auth_header(credentials)
  headers ||= {}
  body = conn.post('/images/create', opts, :headers => headers)
  id = Docker::Util.fix_json(body).last['id']
  new(conn, 'id' => id, :headers => headers)
end

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

Return a specific image.



107
108
109
110
111
# File 'lib/docker/image.rb', line 107

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.



129
130
131
132
133
134
135
136
137
# File 'lib/docker/image.rb', line 129

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



139
140
141
142
143
144
145
146
147
148
# File 'lib/docker/image.rb', line 139

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

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

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



121
122
123
124
125
# File 'lib/docker/image.rb', line 121

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.



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

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 = {}) ⇒ Object

Push the Image to the Docker registry.

Raises:



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

def push(creds = nil, options = {})
  repo_tag = info['RepoTags'].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?

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

#refresh!Object

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



85
86
87
88
89
90
91
92
# File 'lib/docker/image.rb', line 85

def refresh!
  img = Docker::Image.all(:all => true).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.



65
66
67
# File 'lib/docker/image.rb', line 65

def remove(opts = {})
  connection.delete("/images/#{self.id}", 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

#tag(opts = {}) ⇒ Object

Tag the Image.



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

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.



71
72
73
74
# File 'lib/docker/image.rb', line 71

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