class Ufo::Docker::Builder

Public Class Methods

build(options) click to toggle source
# File lib/ufo/docker/builder.rb, line 8
def self.build(options)
  builder = Builder.new(options) # outside if because it need builder.full_image_name
  builder.build
  pusher = Pusher.new(nil, options)
  pusher.push
  builder
end
new(options={}) click to toggle source
# File lib/ufo/docker/builder.rb, line 16
def initialize(options={})
  @options = options
  @dockerfile = options[:dockerfile] || 'Dockerfile'
  @image_namespace = options[:image_namespace] || 'ufo'
end

Public Instance Methods

build() click to toggle source
# File lib/ufo/docker/builder.rb, line 22
def build
  start_time = Time.now
  store_full_image_name

  command = "docker build #{build_options}-t #{full_image_name} -f #{@dockerfile} ."
  say "Building docker image with:".color(:green)
  say "  #{command}".color(:green)
  compile_dockerfile_erb
  check_dockerfile_exists
  update_auth_token
  command = "cd #{Ufo.root} && #{command}"
  success = execute(command, use_system: true)
  unless success
    docker_version_success = system("docker version > /dev/null 2>&1")
    unless docker_version_success
      docker_version_message = "  Are you sure the docker daemon is available?  Try running: docker version."
    end
    puts "ERROR: The docker image fail to build.#{docker_version_message}".color(:red)
    exit 1
  end

  took = Time.now - start_time
  say "Docker image #{full_image_name} built.  "
  say "Docker build took #{pretty_time(took)}.".color(:green)
end
build_options() click to toggle source
# File lib/ufo/docker/builder.rb, line 48
def build_options
  options = ENV['UFO_DOCKER_BUILD_OPTIONS']
  options += " " if options
  options
end
check_dockerfile_exists() click to toggle source
# File lib/ufo/docker/builder.rb, line 98
def check_dockerfile_exists
  unless File.exist?("#{Ufo.root}/#{@dockerfile}")
    puts "#{@dockerfile} does not exist.  Are you sure it exists?"
    exit 1
  end
end
compile() click to toggle source
# File lib/ufo/docker/builder.rb, line 89
def compile
  erb_path = "#{Ufo.root}/#{@dockerfile}.erb"
  if File.exist?(erb_path)
    compile_dockerfile_erb
  else
    puts "File #{erb_path.color(:green)} does not exist. Cannot compile it if it doesnt exist"
  end
end
docker_name_path() click to toggle source
# File lib/ufo/docker/builder.rb, line 139
def docker_name_path
  # output gets entirely wiped by tasks builder so dotn use that folder
  "#{Ufo.root}/.ufo/data/docker_image_name_#{@image_namespace}.txt"
end
ecr_image_names(path) click to toggle source
# File lib/ufo/docker/builder.rb, line 67
def ecr_image_names(path)
  from_image_names(path).select { |i| i =~ /\.amazonaws\.com/ }
end
from_image_names(path) click to toggle source
# File lib/ufo/docker/builder.rb, line 71
def from_image_names(path)
  lines = IO.readlines(path)
  froms = lines.select { |l| l =~ /^FROM/ }
  froms.map do |l|
    md = l.match(/^FROM (.*)/)
    md[1]
  end.compact
end
full_image_name() click to toggle source

full_image - Includes the tag. Examples:

123456789.dkr.ecr.us-west-2.amazonaws.com/myapp:ufo-2018-04-20T09-29-08-b7d51df
tongueroo/demo-ufo:ufo-2018-04-20T09-29-08-b7d51df
# File lib/ufo/docker/builder.rb, line 113
def full_image_name
  return generate_name if @options[:generate]
  return "tongueroo/demo-ufo:ufo-12345678" if ENV['TEST']

  unless File.exist?(docker_name_path)
    puts "Unable to find #{docker_name_path} which contains the last docker image name that was used as a part of `ufo docker build`.  Please run `ufo docker build` first."
    exit 1
  end
  IO.read(docker_name_path).strip
end
generate_name() click to toggle source
# File lib/ufo/docker/builder.rb, line 135
def generate_name
  "#{image_name}:#{@image_namespace}-#{timestamp}-#{git_sha}"
end
git_sha() click to toggle source
# File lib/ufo/docker/builder.rb, line 148
def git_sha
  return @git_sha if @git_sha
  # always call this and dont use the execute method because of the noop option
  @git_sha = `cd #{Ufo.root} && git rev-parse --short HEAD`
  @git_sha.strip!
end
image_name() click to toggle source

full_image - does not include the tag

# File lib/ufo/docker/builder.rb, line 106
def image_name
  settings[:image]
end
pusher() click to toggle source
# File lib/ufo/docker/builder.rb, line 80
def pusher
  @pusher ||= Pusher.new(full_image_name, @options)
end
say(msg) click to toggle source
# File lib/ufo/docker/builder.rb, line 164
def say(msg)
  puts msg unless @options[:mute]
end
store_full_image_name() click to toggle source

Store this in a file because this name gets reference in other tasks later and we want the image name to stay the same when the commands are run separate in different processes. So we store the state in a file. Only when a new docker build command gets run will the image name state be updated.

# File lib/ufo/docker/builder.rb, line 128
def store_full_image_name
  dirname = File.dirname(docker_name_path)
  FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
  full_image_name = generate_name
  IO.write(docker_name_path, full_image_name)
end
timestamp() click to toggle source
# File lib/ufo/docker/builder.rb, line 144
def timestamp
  @timestamp ||= Time.now.strftime('%Y-%m-%dT%H-%M-%S')
end
update_auth_token() click to toggle source

Parse Dockerfile for FROM instruction. If the starting image is from an ECR repository, it's likely an private image so we authorize ECR for pulling.

# File lib/ufo/docker/builder.rb, line 56
def update_auth_token
  ecr_image_names = ecr_image_names("#{Ufo.root}/#{@dockerfile}")
  return if ecr_image_names.empty?

  ecr_image_names.each do |ecr_image_name|
    auth = Ufo::Ecr::Auth.new(ecr_image_name)
    # wont update auth token unless the image being pushed in the ECR image format
    auth.update
  end
end
update_dockerfile() click to toggle source
# File lib/ufo/docker/builder.rb, line 155
def update_dockerfile
  updater = if File.exist?("#{Ufo.root}/Dockerfile.erb") # dont use @dockerfile on purpose
    Variables.new(full_image_name, @options)
  else
    Dockerfile.new(full_image_name, @options)
  end
  updater.update
end

Private Instance Methods

compile_dockerfile_erb() click to toggle source
# File lib/ufo/docker/builder.rb, line 84
def compile_dockerfile_erb
  Compiler.new("#{Ufo.root}/#{@dockerfile}").compile # This path does not have .erb
end