class Minke::Docker::DockerRunner

Public Class Methods

new(logger, network = nil, project = nil) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 4
def initialize logger, network = nil, project = nil
  @network = network ||= 'bridge'
  @logger = logger
  @project = project
end

Public Instance Methods

build_image(dockerfile_dir, name) click to toggle source

build_image creates a new image from the given Dockerfile and name

# File lib/minke/docker/docker_runner.rb, line 164
def build_image dockerfile_dir, name
  ::Docker.options = {:read_timeout => 6200}
  begin
    ::Docker::Image.build_from_dir(dockerfile_dir, {:t => name}) do |v|
      data = /{"stream.*:"(.*)".*/.match(v)
      data = data[1].encode(Encoding.find('UTF-8'), {invalid: :replace, undef: :replace, replace: ''}).chomp('/n') unless data == nil || data.length < 1
      @logger.info data unless data == nil
    end
  rescue => e
    message = e.message
    @logger.error "Error: #{message}" unless message == nil || message.length < 1
  end
end
create_and_run_blocking_container(args) click to toggle source

create_and_run_blocking_container starts a conatainer of the given image name and executes a command, this method blocks until the container exits

Returns:

  • Docker::Container

  • sucess (true if command succeded without error)

# File lib/minke/docker/docker_runner.rb, line 116
def create_and_run_blocking_container args
  host_config = get_port_bindings args
  host_config['NetworkMode'] = @network
  host_config['Binds'] = args[:volumes]

  if args[:links] != nil 
    network = {'EndpointsConfig' => {@network =>
      {'Links' => args[:links].map {|l| "#{@project}_#{l}_1:#{l}"}}
    }}
  end

  exposed_ports = get_exposed_ports args

  # update the timeout for the Excon Http Client
  # set the chunk size to enable streaming of log files
  #::Docker.options = {:chunk_size => 1, :read_timeout => 3600}
  container = ::Docker::Container.create(
          'Image'            => args[:image],
          'Cmd'              => args[:command],
          "Binds"            => args[:volumes],
          "Env"              => args[:environment],
          'WorkingDir'       => args[:working_directory],
    'name'             => args[:name],
    'NetworkMode'      => @network,
    "OpenStdin"        => true,
    "Tty"              => true,
    'PublishAllPorts'  => true,
    'ExposedPorts'     => exposed_ports,
    'HostConfig'       => host_config,
    'NetworkingConfig' => network
  )

  container.start

  success = (container.json['State']['ExitCode'] == 0) ? true: false 
  @logger.error("Unable to start docker container") unless success 

  STDIN.raw do |stdin|
    container.attach(stdin: stdin, tty: true) do |chunk|
      print chunk
    end
  end

  return container, success
end
create_and_run_container(args) click to toggle source

create_and_run_container starts a conatainer of the given image name and executes a command

Returns:

  • Docker::Container

  • sucess (true if command succeded without error)

# File lib/minke/docker/docker_runner.rb, line 68
def create_and_run_container args
  # update the timeout for the Excon Http Client
  # set the chunk size to enable streaming of log files
  ::Docker.options = {:chunk_size => 1, :read_timeout => 3600}
  container = ::Docker::Container.create(
          'Image'           => args[:image],
          'Cmd'             => args[:command],
          "Binds"           => args[:volumes],
          "Env"             => args[:environment],
    'NetworkMode'     => @network,
          'WorkingDir'      => args[:working_directory],
    'name'            => args[:name],
    'PublishAllPorts' => true
  )

  output = ''

  unless args[:deamon] == true
    thread = Thread.new do
      container.attach(:stream => true, :stdin => nil, :stdout => true, :stderr => true, :logs => false, :tty => false) do
        |stream, chunk|
          if chunk.index('[ERROR]') != nil # deal with hidden characters
            @logger.error chunk.gsub(/\[.*\]/,'')
          else
            output += chunk.gsub(/\[.*\]/,'') if output == ''
            output += chunk.gsub(/\[.*\]/,'').prepend("       ") unless output == ''
            @logger.debug chunk.gsub(/\[.*\]/,'')
          end
      end
    end
  end

  container.start
  thread.join unless args[:deamon] == true

  success = (container.json['State']['ExitCode'] == 0) ? true: false 
  @logger.error(output) unless success 

  return container, success
end
delete_container(container) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 182
def delete_container container
  if container != nil
    begin
      container.delete()
    rescue => e
      @logger.error "Error: Unable to delete container: #{e}"
    end
  end
end
docker_version() click to toggle source
# File lib/minke/docker/docker_runner.rb, line 212
def docker_version
  ::Docker.version['Version']
end
find_image(image_name) click to toggle source

find_image finds a docker image in the local registry Returns

Docker::Image

# File lib/minke/docker/docker_runner.rb, line 35
def find_image image_name
  found = nil

  ::Docker::Image.all.each do | image |
          found = image if image.info["RepoTags"] != nil && image.info["RepoTags"].include?(image_name)
  end

  return found
end
get_docker_ip_address() click to toggle source

returns the ip address that docker is running on

# File lib/minke/docker/docker_runner.rb, line 12
def get_docker_ip_address
  # first try to get the ip from docker-ip env
  if !ENV['DOCKER_IP'].to_s.empty?
    return ENV['DOCKER_IP']
  end

  if !ENV['DOCKER_HOST'].to_s.empty?
          # dockerhost set
          host = ENV['DOCKER_HOST'].dup
          host.gsub!(/tcp:\/\//, '')
          host.gsub!(/:\d+/,'')

          return host
  else
    return '127.0.0.1'
  end
end
get_exposed_ports(args) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 234
def get_exposed_ports args
  port_bindings = {}
  if args[:ports] != nil 
    args[:ports].each do |p|
      hostDest = p.split(":")
      port_bindings[hostDest[1] + "/tcp"] = {}
    end
  end

  return port_bindings
end
get_port_bindings(args) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 216
def get_port_bindings args
  host_config = {}
  if args[:ports] != nil 
    port_bindings = {}
    args[:ports].each do |p|
      hostDest = p.split(":")
      if hostDest[0] == ""
        port_bindings[hostDest[1] + "/tcp"] = [{'HostPort' => "#{rand(40000..50000)}", 'HostIp' => "0.0.0.0"}]
      else 
        port_bindings[hostDest[1] + "/tcp"] = [{'HostPort' => hostDest[0], 'HostIp' => "0.0.0.0"}]
      end
    end
    host_config = {'PortBindings' => port_bindings }
  end

  return host_config
end
login_registry(url, user, password, email) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 192
def login_registry url, user, password, email
  if docker_version.start_with? '1.11'
    # email is removed for login in docker 1.11
    system("docker login -u #{user} -p #{password} #{url}")
  else
    system("docker login -u #{user} -p #{password} -e #{email} #{url}")
  end
  $?.exitstatus
end
pull_image(image_name) click to toggle source

pull_image pulls a new copy of the given image from the registry

# File lib/minke/docker/docker_runner.rb, line 47
def pull_image image_name
  ::Docker.options = {:chunk_size => 1, :read_timeout => 3600}
  ::Docker::Image.create('fromImage' => image_name)
end
push_image(image_name) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 207
def push_image image_name
  system("docker push #{image_name}:latest")
  $?.exitstatus ==  0
end
running_containers() click to toggle source

running_images returns a list of running containers Returns

Array of Docker::Image

# File lib/minke/docker/docker_runner.rb, line 57
def running_containers
  containers = ::Docker::Container.all(all: true, filters: { status: ["running"] }.to_json)
  return containers
end
stop_container(container) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 178
def stop_container container
  container.stop()
end
tag_image(image_name, tag) click to toggle source
# File lib/minke/docker/docker_runner.rb, line 202
def tag_image image_name, tag
  image =  self.find_image "#{image_name}:latest"
  image.tag('repo' => tag, 'force' => true) unless image.info["RepoTags"].include? "#{tag}:latest"
end