32
33
34
35
36
37
38
39
40
41
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# File 'lib/baha/builder.rb', line 32
def build!
LOG.info("Building Images")
LOG.debug { "Config: #{@config.inspect}" }
LOG.debug { "Initializing Docker" }
@config.init_docker!
@config.each_image do |image|
build_log = Baha::Log.for_name("Builder [#{image.name}]")
unless image.needs_update?
build_log.info { "Skipped image #{image.name} - No update needed" }
next
end
workspace = Pathname.new(@config.workspace) + image.name
unless workspace.exist?
build_log.debug { "Creating Workspace: #{workspace}" }
FileUtils.mkdir_p workspace.to_s
end
run = false
if image.run
build_log.debug { "Image has RUN commands"}
run = '.init.sh'
File.open(workspace + run,'w') do |f|
f.write("#!/bin/sh\n")
f.write("set -xe\n")
image.run.each do |cmd|
build_log.debug { "Writing command: #{cmd}"}
case cmd
when String
f.write("#{cmd}\n")
when Array
safe = Shellwords.shelljoin(cmd)
f.write("#{safe}\n")
end
end
end
end
build_log.info { "Building #{image.name}" }
if image.pre_build
build_log.debug { "Preparing workspace for #{image.name}" }
image.pre_build.each do |task|
build_log.debug { "execute task: #{task.inspect}" }
Baha::PreBuild::Module.execute(task.merge({ :config => @config, :image => image }))
end
end
command = image.command
if run
command = ["/bin/sh", "#{image.bind}/#{run}"]
end
container_config = {
'Image' => image.parent_id,
'Cmd' => command,
'Workingdir' => image.bind
}
build_log.debug { "Creating container for #{image.name} => #{container_config.inspect}" }
container = Docker::Container.create(container_config)
build_log.debug { "Created container #{container.id} "}
build_log.debug { "Running container for #{image.name}: #{command}" }
container.start({
'Binds' => "#{image.workspace.expand_path}:#{image.bind}"
})
begin
container.streaming_logs({'stdout' => true, 'stderr' => true, 'follow' => true, 'timestamps' => false }) do |out,msg|
case out
when :stdout
build_log.info { "++ #{msg.chomp}" }
when :stderr
build_log.warn { "++ #{msg.chomp}" }
end
end
build_log.debug { "Waiting #{image.timeout} seconds for container #{container.id} to finish building" }
status = container.wait(image.timeout)
rescue Exception => e
build_log.error { "Error building image #{image.name}" }
build_log.error { e }
build_log.info { "Removing container #{container.id}" }
container.stop
container.remove
raise BuildError.new("Interrupted",image)
end
if status['StatusCode'] != 0
build_log.error { "Error building image #{image.name}" }
build_log.info { "Removing container #{container.id}" }
container.remove
raise BuildError.new(status,image)
end
build_log.debug { "Committing Container #{container.id}" }
build_log.debug { "Run Config: #{image.commit_config}" }
build_image = container.commit({'run'=>image.commit_config})
build_log.info { "New Image created: #{build_image.id}"}
build_image = Docker::Image.get(build_image.id)
image.tags.each do |tag|
build_log.debug { "Tagging as #{tag}"}
t = tag.split(/:/)
build_image.tag(:repo => t[0], :tag => t[1])
end
container.remove
end
end
|