-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstrip-layers.rb
executable file
·86 lines (70 loc) · 2.55 KB
/
strip-layers.rb
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
#!/usr/bin/env ruby
require 'json'
require 'tmpdir'
if ARGV.length != 3
STDERR.puts "Usage: #{$0} <base image> <new tag> <comment>"
STDERR.puts "Create a new image with layers commented layers stripped"
exit 64
end
image_id, tag, comment = ARGV
# Make sure the tag is complete.
tag += ':latest' unless tag.include? ':'
# Create a temporary directory to save the image in.
Dir.mktmpdir 'docker-surgery' do |image_dir|
# Move to the directory image directory.
Dir.chdir(image_dir) do
# Save and unpack the image.
system("docker save #{image_id} | tar -x") or exit 1
# Drop legacy files.
File.unlink(*(
Dir['*/json'] + Dir['*/VERSION'] + Dir['repositories']
))
# Read the manifest.
manifests = File.open('manifest.json') { |f| JSON.load(f) }
if manifests.length != 1
abort "Expected one entry in image manifest"
end
manifest = manifests[0]
# Read the config.
config = File.open(manifest['Config']) { |f| JSON.load(f) }
# Remove the layers we're not using.
layers = []
diff_ids = []
history = config['history'].select do |h|
keep = h['comment'] != comment
unless h['empty_layer']
layer_file = manifest['Layers'].shift
diff_id = config['rootfs']['diff_ids'].shift
if layer_file.nil? or diff_id.nil?
abort "Corrupt image"
end
if keep
layers.push layer_file
diff_ids.push diff_id
else
# Also remove the layer file and directory.
File.unlink layer_file
if /^([0-9a-f]{64})\/layer\.tar$/ =~ layer_file
Dir.unlink $~[1]
end
end
end
keep
end
# Verify we did things right.
if manifest['Layers'].length > 0 || config['rootfs']['diff_ids'].length > 0
abort "Corrupt image"
end
# Rewrite the files.
manifest['RepoTags'] = [tag]
manifest['Layers'] = layers
config['rootfs']['diff_ids'] = diff_ids
config['history'] = history
File.open('manifest.json', 'w') { |f| JSON.dump(manifests, f) }
File.open(manifest['Config'], 'w') { |f| JSON.dump(config, f) }
# Pack and load the image.
system("tar -c . | docker load") or exit 1
end
end
# Output the image ID.
system("docker images -q #{tag}") or exit 1