class Docker::Container

This class represents a Docker Container. It’s important to note that nothing is cached so that the information is always up to date.

Public Class Methods

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

Return all of the Containers.

# File lib/docker/container.rb, line 344
def self.all(opts = {}, conn = Docker.connection)
  hashes = Docker::Util.parse_json(conn.get('/containers/json', opts)) || []
  hashes.map { |hash| new(conn, hash) }
end
create(opts = {}, conn = Docker.connection) click to toggle source

Create a new Container.

# File lib/docker/container.rb, line 328
def self.create(opts = {}, conn = Docker.connection)
  query = opts.select {|key| ['name', :name].include?(key) }
  clean_opts = opts.reject {|key| ['name', :name].include?(key) }
  resp = conn.post('/containers/create', query, :body => MultiJson.dump(clean_opts))
  hash = Docker::Util.parse_json(resp) || {}
  new(conn, hash)
end
get(id, opts = {}, conn = Docker.connection) click to toggle source

Return the container with specified ID

# File lib/docker/container.rb, line 337
def self.get(id, opts = {}, conn = Docker.connection)
  container_json = conn.get("/containers/#{id}/json", opts)
  hash = Docker::Util.parse_json(container_json) || {}
  new(conn, hash)
end
prune(conn = Docker.connection) click to toggle source

Prune images

# File lib/docker/container.rb, line 350
def self.prune(conn = Docker.connection)
  conn.post("/containers/prune", {})
  nil
end

Private Class Methods

new(connection, hash={}) click to toggle source

The private new method accepts a connection and a hash of options that must include an id.

# File lib/docker/base.rb, line 12
def initialize(connection, hash={})
  unless connection.is_a?(Docker::Connection)
    raise ArgumentError, "Expected a Docker::Connection, got: #{connection}."
  end
  normalize_hash(hash)
  @connection, @info, @id = connection, hash, hash['id']
  raise ArgumentError, "Must have id, got: #{hash}" unless @id
end

Public Instance Methods

archive_in(inputs, output_path, opts = {}) click to toggle source
# File lib/docker/container.rb, line 280
def archive_in(inputs, output_path, opts = {})
  file_hash = Docker::Util.file_hash_from_paths([*inputs])
  tar = StringIO.new(Docker::Util.create_tar(file_hash))
  archive_in_stream(output_path, opts) do
    tar.read(Excon.defaults[:chunk_size]).to_s
  end
end
archive_in_stream(output_path, opts = {}, &block) click to toggle source
# File lib/docker/container.rb, line 288
def archive_in_stream(output_path, opts = {}, &block)
  overwrite = opts[:overwrite] || opts['overwrite'] || false

  connection.put(
    path_for(:archive),
    { 'path' => output_path, 'noOverwriteDirNonDir' => !overwrite },
    :headers => {
      'Content-Type' => 'application/x-tar'
    },
    &block
  )
  self
end
archive_out(path, &block) click to toggle source
# File lib/docker/container.rb, line 271
def archive_out(path, &block)
  connection.get(
    path_for(:archive),
    { 'path' => path },
    :response_block => block
  )
  self
end
attach(options = {}, excon_params = {}, &block) click to toggle source

Attach to a container’s standard streams / logs.

# File lib/docker/container.rb, line 105
def attach(options = {}, excon_params = {}, &block)
  stdin = options.delete(:stdin)
  tty   = options.delete(:tty)

  opts = {
    :stream => true, :stdout => true, :stderr => true
  }.merge(options)
  # Creates list to store stdout and stderr messages
  msgs = Docker::Messages.new

  if stdin
    # If attaching to stdin, we must hijack the underlying TCP connection
    # so we can stream stdin to the remote Docker process
    opts[:stdin] = true
    excon_params[:hijack_block] = Docker::Util.hijack_for(stdin, block,
      msgs, tty)
  else
    excon_params[:response_block] = Docker::Util.attach_for(block, msgs, tty)
  end

  connection.post(
    path_for(:attach),
    opts,
    excon_params
  )
  [msgs.stdout_messages, msgs.stderr_messages]
end
commit(options = {}) click to toggle source

Create an Image from a Container’s change.s

# File lib/docker/container.rb, line 134
def commit(options = {})
  options.merge!('container' => self.id[0..7])
  # [code](https://github.com/dotcloud/docker/blob/v0.6.3/commands.go#L1115)
  # Based on the link, the config passed as run, needs to be passed as the
  # body of the post so capture it, remove from the options, and pass it via
  # the post body
  config = MultiJson.dump(options.delete('run'))
  hash = Docker::Util.parse_json(
    connection.post('/commit', options, body: config)
  )
  Docker::Image.send(:new, self.connection, hash)
end
delete(options = {})
Alias for: remove
exec(command, options = {}, &block) click to toggle source

Create an Exec instance inside the container

@param command [String, Array] The command to run inside the Exec instance @param options [Hash] The options to pass to Docker::Exec

@return [Docker::Exec] The Exec instance

# File lib/docker/container.rb, line 57
def exec(command, options = {}, &block)
  # Establish values
  tty = options.delete(:tty) || false
  detach = options.delete(:detach) || false
  user = options.delete(:user)
  stdin = options.delete(:stdin)
  stdout = options.delete(:stdout) || !detach
  stderr = options.delete(:stderr) || !detach
  wait = options.delete(:wait)

  opts = {
    'Container' => self.id,
    'User' => user,
    'AttachStdin' => !!stdin,
    'AttachStdout' => stdout,
    'AttachStderr' => stderr,
    'Tty' => tty,
    'Cmd' => command
  }.merge(options)

  # Create Exec Instance
  instance = Docker::Exec.create(
    opts,
    self.connection
  )

  start_opts = {
    :tty => tty,
    :stdin => stdin,
    :detach => detach,
    :wait => wait
  }

  if detach
    instance.start!(start_opts)
    return instance
  else
    instance.start!(start_opts, &block)
  end
end
export(&block) click to toggle source

Export the Container as a tar.

# File lib/docker/container.rb, line 99
def export(&block)
  connection.get(path_for(:export), {}, :response_block => block)
  self
end
kill!(opts = {}) click to toggle source
# File lib/docker/container.rb, line 208
def kill!(opts = {})
  connection.post(path_for(:kill), opts)
  self
end
logs(opts = {}) click to toggle source
# File lib/docker/container.rb, line 160
def logs(opts = {})
  connection.get(path_for(:logs), opts)
end
read_file(path) click to toggle source
# File lib/docker/container.rb, line 302
def read_file(path)
  content = StringIO.new
  archive_out(path) do |chunk|
    content.write chunk
  end

  content.rewind

  Gem::Package::TarReader.new(content) do |tar|
    tar.each do |tarfile|
      return tarfile.read
    end
  end
end
refresh!() click to toggle source

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

e.g. if you would like a live status from the #info hash, call #refresh! first.
# File lib/docker/container.rb, line 10
def refresh!
  other = Docker::Container.all({all: true}, connection).find { |c|
    c.id.start_with?(self.id) || self.id.start_with?(c.id)
  }

  info.merge!(self.json)
  other && info.merge!(other.info) { |key, info_value, other_value| info_value }
  self
end
remove(options = {}) click to toggle source

remove container

# File lib/docker/container.rb, line 250
def remove(options = {})
  connection.delete("/containers/#{self.id}", options)
  nil
end
Also aliased as: delete
rename(new_name) click to toggle source
# File lib/docker/container.rb, line 183
def rename(new_name)
  query = {}
  query['name'] = new_name
  connection.post(path_for(:rename), query)
end
run(cmd, time = 1000) click to toggle source

Given a command and an optional number of seconds to wait for the currently executing command, creates a new Container to run the specified command. If the command that is currently executing does not return a 0 status code, an UnexpectedResponseError is raised.

# File lib/docker/container.rb, line 43
def run(cmd, time = 1000)
  if (code = tap(&:start).wait(time)['StatusCode']).zero?
    commit.run(cmd)
  else
    raise UnexpectedResponseError, "Command returned status code #{code}."
  end
end
start!(opts = {}) click to toggle source
# File lib/docker/container.rb, line 203
def start!(opts = {})
  connection.post(path_for(:start), {}, body: MultiJson.dump(opts))
  self
end
stats(options = {}) { |parse_json| ... } click to toggle source
# File lib/docker/container.rb, line 164
def stats(options = {})
  if block_given?
    options[:read_timeout] ||= 10
    options[:idempotent] ||= false
    parser = lambda do |chunk, remaining_bytes, total_bytes|
      yield Docker::Util.parse_json(chunk)
    end
    begin
      connection.get(path_for(:stats), nil, {response_block: parser}.merge(options))
    rescue Docker::Error::TimeoutError
      # If the container stops, the docker daemon will hold the connection
      # open forever, but stop sending events.
      # So this Timeout indicates the stream is over.
    end
  else
    Docker::Util.parse_json(connection.get(path_for(:stats), {stream: 0}.merge(options)))
  end
end
store_file(path, file_content) click to toggle source
# File lib/docker/container.rb, line 317
def store_file(path, file_content)
  output_io = StringIO.new(
    Docker::Util.create_tar(
      path => file_content
    )
  )

  archive_in_stream("/", overwrite: true) { output_io.read }
end
streaming_logs(opts = {}, &block) click to toggle source
# File lib/docker/container.rb, line 193
def streaming_logs(opts = {}, &block)
  stack_size = opts.delete('stack_size') || opts.delete(:stack_size) || -1
  tty = opts.delete('tty') || opts.delete(:tty) || false
  msgs = Docker::MessagesStack.new(stack_size)
  excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty), idempotent: false}

  connection.get(path_for(:logs), opts, excon_params)
  msgs.messages.join
end
to_s() click to toggle source

Return a String representation of the Container.

# File lib/docker/container.rb, line 148
def to_s
  "Docker::Container { :id => #{self.id}, :connection => #{self.connection} }"
end
top(opts = {}) click to toggle source

Return a List of Hashes that represents the top running processes.

# File lib/docker/container.rb, line 21
def top(opts = {})
  format = opts.delete(:format) { :array }
  resp = Docker::Util.parse_json(connection.get(path_for(:top), opts))
  if resp['Processes'].nil?
    format == :array ? [] : {}
  else
    format == :array ? resp['Processes'].map { |ary| Hash[resp['Titles'].zip(ary)] } : resp
  end
end
update(opts) click to toggle source
# File lib/docker/container.rb, line 189
def update(opts)
  connection.post(path_for(:update), {}, body: MultiJson.dump(opts))
end
wait(time = nil) click to toggle source

Wait for the current command to finish executing. Default wait time is ‘Excon.options`.

# File lib/docker/container.rb, line 33
def wait(time = nil)
  excon_params = { :read_timeout => time }
  resp = connection.post(path_for(:wait), nil, excon_params)
  Docker::Util.parse_json(resp)
end

Private Instance Methods

path_for(resource) click to toggle source

Convenience method to return the path for a particular resource.

# File lib/docker/container.rb, line 356
def path_for(resource)
  "/containers/#{self.id}/#{resource}"
end