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.



194
195
196
197
# File 'lib/docker/container.rb', line 194

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.



177
178
179
180
181
182
183
184
# File 'lib/docker/container.rb', line 177

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



187
188
189
190
191
# File 'lib/docker/container.rb', line 187

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
69
# File 'lib/docker/container.rb', line 42

def attach(options = {}, &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

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



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

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



168
169
170
171
172
173
174
# File 'lib/docker/container.rb', line 168

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



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/docker/container.rb', line 204

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

  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

#kill!(opts = {}) ⇒ Object



115
116
117
118
# File 'lib/docker/container.rb', line 115

def kill!(opts = {})
  connection.post(path_for(:kill), opts)
  self
end

#logs(opts = {}) ⇒ Object



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

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

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

remove container



147
148
149
150
# File 'lib/docker/container.rb', line 147

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)
  else
    raise UnexpectedResponseError, "Command returned status code #{code}."
  end
end

#start!(opts = {}) ⇒ Object



110
111
112
113
# File 'lib/docker/container.rb', line 110

def start!(opts = {})
  connection.post(path_for(:start), {}, :body => opts.to_json)
  self
end

#streaming_logs(opts = {}, &block) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/docker/container.rb', line 102

def streaming_logs(opts = {}, &block)
  msgs = Docker::Messages.new
  excon_params = { response_block: attach_for(block, msgs, false) }

  connection.get(path_for(:logs), opts, excon_params)
  msgs.all_messages.join("\n")
end

#to_sObject

Return a String representation of the Container.



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

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