class Dockerspec::Builder

A class to build a container image.

Public Class Methods

new(*opts) click to toggle source

Constructs a Docker image builder class.

@example Build an Image From CWD or `DOCKERFILE_PATH`

Dockerspec::Builder.new #=> #<Dockerspec::Builder:0x0123>

@example Build an Image from a Directory

Dockerspec::Builder.new('imagedir') #=> #<Dockerspec::Builder:0x0124>

@example Do Not Remove the Image

Dockerspec::Builder.new('../', rm: false)
  #=> #<Dockerspec::Builder:0x0125>

@example Passing Multiple Params

Dockerspec::Builder.new(path: '../', tag: 'myapp', rm: false)
  #=> #<Dockerspec::Builder:0x0125>

@param opts [String, Hash] The `:path` or a list of options.

@option opts [String] :path ('.') The directory or file that contains the

*Dockerfile*. By default tries to read it from the `DOCKERFILE_PATH`
environment variable and uses `'.'` if it is not set.

@option opts [String] :string Use this string as Dockerfile instead of

`:path`. Not set by default.

@option opts [String] :string_build_path Used to specify the path that is

used for the docker build of a string *Dockerfile*. This enables ADD
statements in the Dockerfile to access files that are outside of .
Not set by default and overrides the default '.'

@option opts [String] :template Use this [Erubis]

(http://www.kuwata-lab.com/erubis/users-guide.html) template file as
*Dockerfile*.

@option opts [String] :id Use this Docker image ID instead of a

*Dockerfile*.

@option opts [Boolean] :rm Whether to remove the generated docker images

after running the tests. By default only removes them if it is running
on a CI machine.

@option opts [Hash, Erubis::Context] :context ({}) Template context

used when the `:template` source is used.

@option opts [String] :tag Repository tag to be applied to the resulting

image.

@option opts [Integer, Symbol] :log_level Sets the docker library

verbosity level. Possible values:
 `:silent` or `0` (no output),
 `:ci` or `1` (enables some outputs recommended for CI environments),
 `:info` or `2` (gives information about main build steps),
 `:debug` or `3` (outputs all the provided information in its raw
   original form).

@see Dockerspec::RSpec::Resources#docker_build

@api public

# File lib/dockerspec/builder.rb, line 95
def initialize(*opts)
  @image = nil
  @options = parse_options(opts)
end

Public Instance Methods

build() click to toggle source

Builds the docker image.

@example Build an Image From a Path

d = Dockerspec::Builder.new(path: 'dockerfile_dir')
d.build #=> #<Dockerspec::Builder:0x0125>

@return [String] Docker image ID.

@raise [Dockerspec::DockerError] For underlaying docker errors.

@api public

# File lib/dockerspec/builder.rb, line 129
def build
  send("build_from_#{source}", @options[source])
  self
end
id() click to toggle source

Returns Docker image ID.

@example Get the Image ID After Building the Image

d = Dockerspec::Builder.new
d.build
d.id #=> "9f8866b49bfb[...]"

@return [String] Docker image ID.

@api public

# File lib/dockerspec/builder.rb, line 112
def id
  @image.id
end
to_s() click to toggle source

Gets a descriptions of the object.

@example

d = Dockerspec::Builder.new('.')
d.to_s #=> "Docker Build from path: ."

@return [String] The object description.

@api public

# File lib/dockerspec/builder.rb, line 145
def to_s
  description('Docker Build from')
end

Protected Instance Methods

add_repository_tag() click to toggle source

Adds a repository name and a tag to the Docker image.

@return void

@api private

# File lib/dockerspec/builder.rb, line 408
def add_repository_tag
  return unless @options.key?(:tag)
  repo, repo_tag = @options[:tag].split(':', 2)
  @image.tag(repo: repo, tag: repo_tag, force: true)
end
build_block() click to toggle source

Generates the Ruby block used to parse the logs during image construction.

@return [Proc] The Ruby block.

@api private

# File lib/dockerspec/builder.rb, line 267
def build_block
  proc { |chunk| logger.print_chunk(chunk) }
end
build_from_dir(dir) click to toggle source

Builds the image from a directory with a Dockerfile.

It also saves the generated image in the object internally.

@param dir [String] The directory path.

@return void

@raise [Dockerspec::DockerError] For underlaying docker errors.

@api private

# File lib/dockerspec/builder.rb, line 332
def build_from_dir(dir)
  image(::Docker::Image.build_from_dir(dir, &build_block))
  add_repository_tag
rescue ::Docker::Error::DockerError => e
  DockerExceptionParser.new(e)
end
build_from_file(file) click to toggle source

Builds the image from a file that is not called Dockerfile.

It also saves the generated image in the object internally.

This creates a temporary directory where it copies all the files and generates the temporary Dockerfile.

@param file [String] The Dockerfile file path.

@return void

@api private

# File lib/dockerspec/builder.rb, line 313
def build_from_file(file)
  dir = File.dirname(file)
  string = IO.read(file)
  build_from_string(string, dir)
end
build_from_id(id) click to toggle source

Gets the image from a Image ID.

It also saves the image in the object internally.

@param id [String] The Docker image ID.

@return void

@raise [Dockerspec::DockerError] For underlaying docker errors.

@api private

# File lib/dockerspec/builder.rb, line 391
def build_from_id(id)
  @image = ::Docker::Image.get(id)
  add_repository_tag
rescue ::Docker::Error::NotFoundError
  @image = ::Docker::Image.create('fromImage' => id)
  add_repository_tag
rescue ::Docker::Error::DockerError => e
  DockerExceptionParser.new(e)
end
build_from_path(path) click to toggle source

Builds the image from a directory or a file.

It also saves the generated image in the object internally.

@param path [String] The path.

@return void

@api private

# File lib/dockerspec/builder.rb, line 350
def build_from_path(path)
  if !File.directory?(path) && File.basename(path) == 'Dockerfile'
    path = File.dirname(path)
  end
  File.directory?(path) ? build_from_dir(path) : build_from_file(path)
end
build_from_string(string, dir = '.') click to toggle source

Builds the image from a string. Generates the Docker tag if required.

It also saves the generated image in the object internally.

This creates a temporary directory where it copies all the files and generates the temporary Dockerfile.

@param string [String] The Dockerfile content. @param dir [String] The directory to copy the files from. Files that are

required by the Dockerfile passed in *string*. If not passed, then
the 'string_build_path' option is used. If that is not used, '.' is
assumed.

@return void

@api private

# File lib/dockerspec/builder.rb, line 289
def build_from_string(string, dir = '.')
  dir = @options[:string_build_path] if @options[:string_build_path]
  Dir.mktmpdir do |tmpdir|
    FileUtils.cp_r("#{dir}/.", tmpdir)
    dockerfile = File.join(tmpdir, 'Dockerfile')
    File.open(dockerfile, 'w') { |f| f.write(string) }
    build_from_dir(tmpdir)
  end
end
build_from_template(file) click to toggle source

Builds the image from a template.

It also saves the generated image in the object internally.

@param file [String] The Dockerfile [Erubis] (www.kuwata-lab.com/erubis/users-guide.html) template path.

@return void

@api private

# File lib/dockerspec/builder.rb, line 369
def build_from_template(file)
  context = @options[:context] || {}

  template = IO.read(file)
  eruby = Erubis::Eruby.new(template)
  string = eruby.evaluate(context)
  build_from_string(string, File.dirname(file))
end
default_options() click to toggle source

Gets the default configuration options after merging them with RSpec configuration options.

@example

self.default_options #=> {:path=>".", :rm=>true, :log_level=>:silent}

@return [Hash] The configuration options.

@api private

# File lib/dockerspec/builder.rb, line 230
def default_options
  {
    path: ENV['DOCKERFILE_PATH'] || '.',
    # Autoremove images in all CIs except Travis (not supported):
    rm: ci? && !travis_ci?,
    # Avoid CI timeout errors:
    log_level: ci? ? :ci : :silent
  }.merge(rspec_options)
end
image(img = nil) click to toggle source

Sets or gets the Docker image.

@param img [Docker::Image] The Docker image to set.

@return [Docker::Image] The Docker image object.

@api private

# File lib/dockerspec/builder.rb, line 194
def image(img = nil)
  return @image if img.nil?
  ImageGC.instance.add(img.id) if @options[:rm]
  @image = img
end
logger() click to toggle source

Gets the Docker Logger to use during the build process.

@return void

@api private

# File lib/dockerspec/builder.rb, line 421
def logger
  @logger ||= Logger.instance(@options[:log_level])
end
parse_options(opts) click to toggle source

Parses the configuration options passed to the constructor.

@example

self.parse_options #=> {:path=>".", :rm=>true, :log_level=>:silent}

@param opts [Array<String, Hash>] The list of optitag. The strings will

be interpreted as `:path`, others will be merged.

@return [Hash] The configuration options.

@see initialize

@api private

# File lib/dockerspec/builder.rb, line 255
def parse_options(opts)
  opts_hs_ary = opts.map { |x| x.is_a?(Hash) ? x : { path: x } }
  opts_hs_ary.reduce(default_options) { |a, e| a.merge(e) }
end
rspec_options() click to toggle source

Gets the default options configured using `RSpec.configuration`.

@example

self.rspec_options #=> {:path=>".", :rm=>true, :log_level=>:silent}

@return [Hash] The configuration options.

@api private

# File lib/dockerspec/builder.rb, line 210
def rspec_options
  config = ::RSpec.configuration
  {}.tap do |opts|
    opts[:path] = config.dockerfile_path if config.dockerfile_path?
    opts[:rm] = config.rm_build if config.rm_build?
    opts[:log_level] = config.log_level if config.log_level?
  end
end
source() click to toggle source

Gets the source to generate the image from.

Possible values: `:string`, `:template`, `:id`, `:path`.

@example Building an Image from a Path

self.source #=> :path

@example Building an Image from a Template

self.source #=> :template

@return [Symbol] The source.

@api private

# File lib/dockerspec/builder.rb, line 166
def source
  return @source unless @source.nil?
  @source = %i(string template id path).find { |from| @options.key?(from) }
end