Class: Hoosegow::Docker

Inherits:
Object
  • Object
show all
Defined in:
lib/hoosegow/docker.rb

Overview

Minimal API client for Docker, allowing attaching to container stdin/stdout/stderr.

Constant Summary collapse

DEFAULT_HOST =
"127.0.0.1"
DEFAULT_PORT =
4243
DEFAULT_SOCKET =
"/var/run/docker.sock"

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Docker

Initialize a new Docker API client.

options - Connection options.

:host   - IP or hostname to connect to (unless using Unix
          socket).
:port   - TCP port to connect to (unless using Unix socket).
:socket - Path to local Unix socket (unless using host and
          port).
:after_create - A proc that will be called after a container is created.
:after_start  - A proc that will be called after a container is started.
:after_stop   - A proc that will be called after a container stops.
:prestart - Start a new container after each `run_container` call.
:volumes  - A mapping of volumes to mount in the container. e.g.
            if the Dockerfile has `VOLUME /work`, where the container will
            write data, and `VOLUME /config` where read-only configuration
            is, you might use
              :volumes => {
                "/config" => "/etc/shared-config",
                "/work"   => "/data/work:rw",
              }
            `:volumes => { "/work" => "/home/localuser/work/to/do" }`
:Other - any option with a capitalized key will be passed on
         to the 'create container' call. See http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.9/#create-a-container


40
41
42
43
44
45
46
47
48
# File 'lib/hoosegow/docker.rb', line 40

def initialize(options = {})
  set_docker_url! options
  @after_create      = options[:after_create]
  @after_start       = options[:after_start]
  @after_stop        = options[:after_stop]
  @volumes           = options[:volumes]
  @prestart          = options.fetch(:prestart, true)
  @container_options = options.select { |k,v| k =~ /\A[A-Z]/ }
end

Instance Method Details

#attach_container(data, &block) ⇒ Object

Attach to a container, writing data to container’s STDIN.

Returns combined STDOUT/STDERR from container.



106
107
108
109
# File 'lib/hoosegow/docker.rb', line 106

def attach_container(data, &block)
  stdin = StringIO.new data
  @container.attach :stdin => stdin, &block
end

#build_image(name, tarfile) ⇒ Object

Public: Build a new image.

name - The name to give the image. tarfile - Tarred data for creating image. See docs.docker.io/en/latest/api/docker_remote_api_v1.5/#build-an-image-from-dockerfile-via-stdin

Returns Array of build result objects from the Docker API.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/hoosegow/docker.rb', line 144

def build_image(name, tarfile)
  # Setup parser to receive chunks and yield parsed JSON objects.
  ret = []
  error = nil
  parser = Yajl::Parser.new
  parser.on_parse_complete = Proc.new do |obj|
    ret << obj
    error = Hoosegow::ImageBuildError.new(obj) if obj["error"]
    yield obj if block_given?
  end

  # Make API call to create image.
  opts = {:t => name, :rm => '1'}
  ::Docker::Image.build_from_tar StringIO.new(tarfile), opts do |chunk|
    parser << chunk
  end

  raise error if error

  # Return Array of received objects.
  ret
end

#create_container(image) ⇒ Object

Public: Create a container using the specified image.

image - The name of the image to start the container with.

Returns nothing.



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/hoosegow/docker.rb', line 81

def create_container(image)
  create_options = default_container_options(image)

  # Merge in additional :HostConfig options into default options
  if @container_options.has_key?(:HostConfig)
    create_options[:HostConfig].merge!(@container_options[:HostConfig])
  end

  @container = ::Docker::Container.create @container_options.merge(
    create_options
  )
  callback @after_create
end

#delete_containerObject

Public: Delete the last started container.

Returns response body or nil if no container was started.



131
132
133
134
135
136
# File 'lib/hoosegow/docker.rb', line 131

def delete_container
  return unless @container
  @container.delete :v => 1
rescue ::Docker::Error::ServerError => e
  $stderr.puts "Docker could not delete #{@container.id}: #{e}"
end

#image_exist?(name) ⇒ Boolean

Check if a Docker image exists.

name - The name of the image to check for.

Returns true/false.

Returns:

  • (Boolean)


172
173
174
# File 'lib/hoosegow/docker.rb', line 172

def image_exist?(name)
  ::Docker::Image.exist? name
end

#run_container(image, data, &block) ⇒ Object

Public: Create and start a Docker container if one hasn’t been started already, then attach to it its stdin/stdout.

image - The image to run. data - The data to pipe to the container’s stdin.

Returns the data from the container’s stdout.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/hoosegow/docker.rb', line 57

def run_container(image, data, &block)
  unless @prestart && @container
    create_container(image)
    start_container
  end

  begin
    attach_container(data, &block)
  ensure
    wait_container
    delete_container
    if @prestart
      create_container(image)
      start_container
    end
  end
  nil
end

#start_containerObject

Public: Start a Docker container.

Returns nothing.



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

def start_container
  @container.start
  callback @after_start
end

#stop_containerObject

Public: Stop the running container.

Returns response body or nil if no container is running.



122
123
124
125
126
# File 'lib/hoosegow/docker.rb', line 122

def stop_container
  return unless @container
  @container.stop :timeout => 0
  callback @after_stop
end

#wait_containerObject

Public: Wait for a container to finish.

Returns nothing.



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

def wait_container
  @container.wait
  callback @after_stop
end