Class: Docker::Container

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

Overview

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

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 all of the Containers.



165
166
167
168
# File 'lib/docker/container.rb', line 165

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) ⇒ Object

Create a new Container.



148
149
150
151
152
153
154
155
# File 'lib/docker/container.rb', line 148

def self.create(opts = {}, conn = Docker.connection)
  name = opts.delete('name')
  query = {}
  query['name'] = name if name
  resp = conn.post('/containers/create', query, :body => opts.to_json)
  hash = Docker::Util.parse_json(resp) || {}
  new(conn, hash)
end

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

Return the container with specified ID



158
159
160
161
162
# File 'lib/docker/container.rb', line 158

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

Instance Method Details

#attach(options = {}, &block) ⇒ Object

Attach to a container’s standard streams / logs.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/docker/container.rb', line 42

def attach(options = {}, &block)
  stdin = options.delete(:stdin)

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

  excon_params = {}

  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] = hijack_for(stdin, block, msgs)
  else
    excon_params[:response_block] = attach_for(block, msgs)
  end

  connection.post(
    path_for(:attach),
    opts,
    excon_params
  )
  [msgs.stdout_messages, msgs.stderr_messages]
end

#commit(options = {}) ⇒ Object

Create an Image from a Container’s change.s



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/docker/container.rb', line 71

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 = options.delete('run')
  hash = Docker::Util.parse_json(connection.post('/commit',
                                                 options,
                                                 :body => config.to_json))
  Docker::Image.send(:new, self.connection, hash)
end

#copy(path, &block) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/docker/container.rb', line 139

def copy(path, &block)
  connection.post(path_for(:copy), {},
    :body => { "Resource" => path }.to_json,
    :response_block => block
  )
  self
end

#export(&block) ⇒ Object

Export the Container as a tar.



36
37
38
39
# File 'lib/docker/container.rb', line 36

def export(&block)
  connection.get(path_for(:export), {}, :response_block => block)
  self
end

#hijack_for(stdin, block, msg_stack) ⇒ Object



175
176
177
178
179
180
181
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
209
# File 'lib/docker/container.rb', line 175

def hijack_for(stdin, block, msg_stack)
  attach_block = attach_for(block, msg_stack)

  lambda do |socket|
    debug "hijack: hijacking the HTTP socket"
    threads = []

    debug "hijack: starting stdin copy thread"
    threads << Thread.start do
      debug "hijack: copying stdin => socket"
      IO.copy_stream stdin, socket

      debug "hijack: closing write end of hijacked socket"
      socket.close_write
    end

    debug "hijack: starting hijacked socket read thread"
    threads << Thread.start do
      debug "hijack: reading from hijacked socket"

      begin
        while chunk = socket.readpartial(512)
          debug "hijack: got #{chunk.bytesize} bytes from hijacked socket"
          attach_block.call chunk, nil, nil
        end
      rescue EOFError
      end

      debug "hijack: killing stdin copy thread"
      threads.first.kill
    end

    threads.each(&:join)
  end
end

#logs(opts = {}) ⇒ Object



97
98
99
# File 'lib/docker/container.rb', line 97

def logs(opts = {})
  connection.get(path_for(:logs), opts)
end

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

remove container



133
134
135
136
# File 'lib/docker/container.rb', line 133

def remove(options = {})
  connection.delete("/containers/#{self.id}", options)
  nil
end

#run(cmd, time = 1000) ⇒ Object

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.



27
28
29
30
31
32
33
# File 'lib/docker/container.rb', line 27

def run(cmd, time = 1000)
  if (code = tap(&:start).wait(time)['StatusCode']).zero?
    commit.run(cmd).tap(&:start)
  else
    raise UnexpectedResponseError, "Command returned status code #{code}."
  end
end

#to_sObject

Return a String representation of the Container.



85
86
87
# File 'lib/docker/container.rb', line 85

def to_s
  "Docker::Container { :id => #{self.id}, :connection => #{self.connection} }"
end

#top(opts = {}) ⇒ Object

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



7
8
9
10
11
12
13
14
# File 'lib/docker/container.rb', line 7

def top(opts = {})
  resp = Docker::Util.parse_json(connection.get(path_for(:top), opts))
  if resp['Processes'].nil?
    []
  else
    resp['Processes'].map { |ary| Hash[resp['Titles'].zip(ary)] }
  end
end

#wait(time = nil) ⇒ Object

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



18
19
20
21
# File 'lib/docker/container.rb', line 18

def wait(time = nil)
  resp = connection.post(path_for(:wait), nil, :read_timeout => time)
  Docker::Util.parse_json(resp)
end