-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdflatten
More file actions
executable file
·142 lines (112 loc) · 3.13 KB
/
dflatten
File metadata and controls
executable file
·142 lines (112 loc) · 3.13 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
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
#!/bin/bash
function containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
function findImages () {
jq $1 /var/lib/docker/repositories-aufs | sed "s/\"//g"
}
function readLayers () {
local arr
readarray -t arr < <(cat /var/lib/docker/aufs/layers/$1)
local farr=("$1")
farr+=("${arr[@]}")
echo ${farr[@]}
}
function mountLayers () {
#declare -a layers=("${!1}")
for i in "${!1}"
do
mount -o remount,append:"/var/lib/docker/aufs/diff/$i/"=ro+wh $2
done
}
while [[ $# > 1 ]]
do
key="$1"
shift
case $key in
-o|--original)
ORIGINAL_ARG="$1"
shift
;;
-t|--target)
TARGET_ARG="$1"
shift
;;
*)
# unknown option
;;
esac
done
if [ -z "$ORIGINAL_ARG" ]; then
echo "$(basename "$0") -o original_image_name -t target_image_name "
exit 1
fi
arrIN=(${ORIGINAL_ARG//:/ })
ORIGINAL_NAME=${arrIN[0]}
ORIGINAL_TAG=${arrIN[1]:=latest}
arrIN=(${TARGET_ARG//:/ })
TARGET_NAME=${arrIN[0]:=${ORIGINAL_NAME}_flatten}
TARGET_TAG=${arrIN[1]:=$ORIGINAL_TAG}
TEMP_DIR=`mktemp -d`
### Find tagged images
readarray -t TAGGED_IMAGES < <(findImages '.["Repositories"]|.[]|.[]')
### Find original image ID
ORIGINAL_ID=`findImages '.["Repositories"]|.["'$ORIGINAL_NAME'"]|.["'$ORIGINAL_TAG'"]'`
if [ "null" = "$ORIGINAL_ID" ]; then
echo "Can't find image $ORIGINAL_NAME:$ORIGINAL_TAG"
exit 1
fi
### Target ID is reverse of original ID, so its stable
TARGET_ID=`echo $ORIGINAL_ID | rev`
### Do we have image in cache?
if [ -f "/var/lib/docker/aufs/layers/"$TARGET_ID ]; then
echo Using cache
echo $TARGET_ID
docker tag $TARGET_ID $TARGET_NAME:$TARGET_TAG
exit 0
else
echo Flatten image to $TARGET_ID
fi
### Find all layers of original image
ORIGINAL_LAYERS=( $(readLayers $ORIGINAL_ID) )
ORIGINAL_PARENT_ID=${ORIGINAL_LAYERS[1]}
### Find parent ID
for i in "${ORIGINAL_LAYERS[@]:1}"
do
containsElement $i "${TAGGED_IMAGES[@]}"
if [ "$?" == "0" ]
then
PARENT_ID=$i
break
fi
done
### Find parent images
PARENT_LAYERS=( $(readLayers $PARENT_ID) )
### Make temp folders
ORIGINAL_DIR=$TEMP_DIR/source
FLATTEN_DIR=$TEMP_DIR/flatten
mkdir $FLATTEN_DIR
mkdir $ORIGINAL_DIR
mkdir $TEMP_DIR/empty
mkdir $TEMP_DIR/diff
### Recovery original image
mount -t aufs -o ro,br:$TEMP_DIR/empty none $ORIGINAL_DIR
mountLayers ORIGINAL_LAYERS[@] $ORIGINAL_DIR
### Build diff
mount -t aufs -o rw,br:$TEMP_DIR/diff/=rw none $FLATTEN_DIR
mountLayers PARENT_LAYERS[@] $FLATTEN_DIR
rsync -aAXvq --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} --delete "$ORIGINAL_DIR/" $FLATTEN_DIR
umount $FLATTEN_DIR
umount $ORIGINAL_DIR
### Build tar for load
LL_DIR=$TEMP_DIR/result/$TARGET_ID
mkdir -p $LL_DIR
tar -cpf $LL_DIR/layer.tar --numeric-owner -C $TEMP_DIR/diff .
echo 1.0 > $LL_DIR/VERSION
cat /var/lib/docker/graph/$ORIGINAL_ID/json | sed s/$ORIGINAL_ID/$TARGET_ID/g | sed s/$ORIGINAL_PARENT_ID/$PARENT_ID/g > $LL_DIR/json
echo '{"'$TARGET_NAME'":{"'$TARGET_TAG'":"'$TARGET_ID'"}}' > $TEMP_DIR/result/repositories
tar -cpf $TEMP_DIR/tmp.tar --numeric-owner -C $TEMP_DIR/result .
docker load < $TEMP_DIR/tmp.tar
rm -r $TEMP_DIR