class Docker::Image

This class represents a Docker Image.

Public Class Methods

all(opts = {}, conn = Docker.connection) click to toggle source

Return every Image.

# File lib/docker/image.rb, line 193
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) click to toggle source

Given a Dockerfile as a string, builds an Image.

# File lib/docker/image.rb, line 230
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) click to toggle source

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.

# File lib/docker/image.rb, line 268
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) click to toggle source

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.

# File lib/docker/image.rb, line 246
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) click to toggle source

Create a new Image.

# File lib/docker/image.rb, line 110
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)
    )
  image = opts['fromImage'] || opts[:fromImage]
  get(image, {}, conn)
end
exist?(id, opts = {}, conn = Docker.connection) click to toggle source

Check if an image exists.

# File lib/docker/image.rb, line 185
def exist?(id, opts = {}, conn = Docker.connection)
  get(id, opts, conn)
  true
rescue Docker::Error::NotFoundError
  false
end
get(id, opts = {}, conn = Docker.connection) click to toggle source

Return a specific image.

# 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) click to toggle source

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

# File lib/docker/image.rb, line 208
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) click to toggle source
# File lib/docker/image.rb, line 218
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
load(tar, opts = {}, conn = Docker.connection, creds = nil, &block) click to toggle source

Load a tar Image

# File lib/docker/image.rb, line 172
def load(tar, opts = {}, conn = Docker.connection, creds = nil, &block)
   headers = build_headers(creds)
   io = tar.is_a?(String) ? File.open(tar, 'rb') : tar
   body = ""
   conn.post(
     '/images/load',
     opts,
     :headers => headers,
     :response_block => response_block(body, &block)
   ) { io.read(Excon.defaults[:chunk_size]).to_s }
end
save(names, filename = nil, conn = Docker.connection) click to toggle source

Save the raw binary representation or one or more Docker images

@param names [String, Array#String] The image(s) you wish to save @param filename [String] The file to export the data to. @param conn [Docker::Connection] The Docker connection to use

@return [NilClass, String] If filename is nil, return the string representation of the binary data. If the filename is not nil, then return nil.

# File lib/docker/image.rb, line 140
def save(names, filename = nil, conn = Docker.connection)
  if filename
    File.open(filename, 'wb') do |file|
      save_stream(names, {}, conn, &response_block_for_save(file))
    end
    nil
  else
    string = ''
    save_stream(names, {}, conn, &response_block_for_save(string))
    string
  end
end
save_stream(names, opts = {}, conn = Docker.connection, &block) click to toggle source

Stream the contents of Docker image(s) to a block.

@param names [String, Array#String] The image(s) you wish to save @param conn [Docker::Connection] The Docker connection to use @yield chunk [String] a chunk of the Docker image(s).

# File lib/docker/image.rb, line 158
def save_stream(names, opts = {}, conn = Docker.connection, &block)
  # By using compare_by_identity we can create a Hash that has
  # the same key multiple times.
  query = {}.tap(&:compare_by_identity)
  Array(names).each { |name| query['names'.dup] = URI.encode(name) }
  conn.get(
    '/images/get',
    query,
    opts.merge(:response_block => block)
  )
  nil
end

Private Class Methods

build_headers(creds=nil) click to toggle source

A method to build the config header and merge it into the headers sent by build_from_dir.

# File lib/docker/image.rb, line 285
def self.build_headers(creds=nil)
  credentials = creds || Docker.creds || {}
  config_header = Docker::Util.build_config_header(credentials)

  headers = { 'Content-Type'      => 'application/tar',
              'Transfer-Encoding' => 'chunked' }
  headers = headers.merge(config_header) if config_header
  headers
end
response_block(body) { |chunk| ... } click to toggle source

Generates the block to be passed as a reponse block to Excon. The returned lambda will append Docker output to the first argument, and yield output to the passed block, if a block is given.

# File lib/docker/image.rb, line 321
def self.response_block(body)
  lambda do |chunk, remaining, total|
    body << chunk
    yield chunk if block_given?
  end
end
response_block_for_save(file) click to toggle source

Generates the block to be passed in to the save request. This lambda will append the streaming data to the file provided.

# File lib/docker/image.rb, line 330
def self.response_block_for_save(file)
  lambda do |chunk, remianing, total|
    file << chunk
  end
end

Public Instance Methods

delete(opts = {})
Alias for: remove
insert_local(opts = {}) click to toggle source

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

# 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) click to toggle source

Push the Image to the Docker registry.

# 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!() click to toggle source

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

# File lib/docker/image.rb, line 98
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 = {}) click to toggle source

Remove the Image from the server.

# File lib/docker/image.rb, line 67
def remove(opts = {})
  name = opts.delete(:name) || self.id
  connection.delete("/images/#{name}", opts)
end
Also aliased as: delete
run(cmd=nil) click to toggle source

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

# 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) click to toggle source

Save the image as a tarball

# File lib/docker/image.rb, line 88
def save(filename = nil)
  self.class.save(self.id, filename, connection)
end
save_stream(opts = {}, &block) click to toggle source

Save the image as a tarball to an IO object.

# File lib/docker/image.rb, line 93
def save_stream(opts = {}, &block)
  self.class.save_stream(self.id, opts, connection, &block)
end
tag(opts = {}) click to toggle source

Tag the Image.

# 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_s() click to toggle source

Return a String representation of the Image.

# File lib/docker/image.rb, line 74
def to_s
  "Docker::Image { :id => #{self.id}, :info => #{self.info.inspect}, "\
    ":connection => #{self.connection} }"
end

Private Instance Methods

dockerfile_for(file_hash, output_path) click to toggle source

Convience method to get the Dockerfile for a file hash and a path to output to.

# File lib/docker/image.rb, line 303
def dockerfile_for(file_hash, output_path)
  dockerfile = "from #{self.id}\n"

  file_hash.keys.each do |basename|
    dockerfile << "add #{basename} #{output_path}\n"
  end

  dockerfile
end
ensure_repo_tags() click to toggle source
# File lib/docker/image.rb, line 313
def ensure_repo_tags
  refresh! unless info.has_key?('RepoTags')
  info['RepoTags']
end
path_for(resource) click to toggle source

Convenience method to return the path for a particular resource.

# File lib/docker/image.rb, line 296
def path_for(resource)
  "/images/#{self.id}/#{resource}"
end