-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker-build
More file actions
executable file
·115 lines (97 loc) · 2.92 KB
/
docker-build
File metadata and controls
executable file
·115 lines (97 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
#!/usr/bin/env ruby
require 'docker-api'
require 'fileutils'
require 'open3'
require 'optparse'
require 'pathname'
require 'tmpdir'
DEFAULT_IMAGE_NAME = ''
Dockerfile = Struct.new(:name, :lines)
def extract(container, source_file, destination_directory)
destination = destination_directory / source_file
destination.dirname.mkpath
Open3.popen2('tar', 'x', '-C', destination.dirname.to_s) do |tar_in, tar_out|
container.copy(source_file.to_s) do |chunk|
tar_in << chunk
end
tar_in.close
tar_out.close
end
end
tags = {}
OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options] PATH"
opts.on '-tTAG', '--tag=TAG', 'Image tag, in the format <DOCKERFILE-NAME>=<NAME>:<TAG>' do |tag|
image_name, tag_name = tag.split('=', 2)
if tag_name.nil?
image_name, tag_name = [DEFAULT_IMAGE_NAME, image_name]
end
tags[image_name] = tag_name
end
end.parse!
path = Pathname.new(ARGV[0]).expand_path
parent_dockerfile = (path / 'Dockerfile').readlines
dockerfiles = parent_dockerfile
.slice_when { |before, after|
after.start_with?('NAME ') || (!before.start_with?('NAME ') && after.start_with?('FROM '))
}.collect { |dockerfile|
dockerfile.unshift('NAME ' + DEFAULT_IMAGE_NAME) unless dockerfile[0].start_with?('NAME ')
name_line, *lines = dockerfile
name = name_line[5, name_line.length].strip
Dockerfile.new(name, lines)
}
images = {}
failed = false
dockerfiles.each do |dockerfile|
next if failed
lines = []
image_files = {}
dockerfile.lines.each do |line|
if line =~ /^COPY (\w+):\/(.+?) (.+)$/m
image_files[$1] ||= []
image_files[$1] << $2
lines << "COPY .containers/#{$1}/#{$2} #{$3}"
else
lines << line
end
end
dockerfile.lines = lines
Dir.mktmpdir do |dir_string|
dir = Pathname.new(dir_string)
(dir / '.containers').mkdir unless image_files.empty?
image_files.each do |image_name, files|
container = Docker::Container.create('Image' => images[image_name].id, 'Cmd' => ['true'])
destination_directory = dir / '.containers' / image_name
begin
container.start
files.each do |file|
extract container, file, destination_directory
end
ensure
container.delete
end
end
FileUtils.cp_r "#{path}/.", dir.to_s
(dir / 'Dockerfile').write(dockerfile.lines.join)
begin
images[dockerfile.name] = Docker::Image.build_from_dir(dir_string) do |streaming_lines|
streaming_lines.each_line do |line|
log = JSON.parse(line)
if log && log.has_key?('stream')
print log['stream']
elsif log.has_key?('errorDetail')
puts log['errorDetail']['message']
end
end
end
rescue Docker::Error::UnexpectedResponseError
failed = true
end
end
end
images.each do |image_name, image|
if tags[image_name]
image.tag('repo' => tags[image_name])
end
end
exit 1 if failed