forked from meltwater/docker-cleanup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.sh
executable file
·220 lines (190 loc) · 7.71 KB
/
run.sh
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/bin/bash
checkPatterns() {
keepit=$3
if [ -n "$1" ]; then
for PATTERN in $(echo $1 | tr "," "\n"); do
if [[ "$2" = $PATTERN* ]]; then
if [ $DEBUG ]; then echo "DEBUG: Matches $PATTERN - keeping"; fi
keepit=1
else
if [ $DEBUG ]; then echo "DEBUG: No match for $PATTERN"; fi
fi
done
fi
return $keepit
}
if [ ! -e "/var/run/docker.sock" ]; then
echo "=> Cannot find docker socket(/var/run/docker.sock), please check the command!"
exit 1
fi
if docker version >/dev/null; then
echo "docker is running properly"
else
echo "Cannot run docker binary at /usr/bin/docker"
echo "Please check if the docker binary is mounted correctly"
exit 1
fi
if [ "${CLEAN_PERIOD}" == "**None**" ]; then
echo "=> CLEAN_PERIOD not defined, use the default value."
CLEAN_PERIOD=1800
fi
if [ "${DELAY_TIME}" == "**None**" ]; then
echo "=> DELAY_TIME not defined, use the default value."
DELAY_TIME=1800
fi
if [ "${KEEP_IMAGES}" == "**None**" ]; then
unset KEEP_IMAGES
fi
if [ "${KEEP_CONTAINERS}" == "**None**" ]; then
unset KEEP_CONTAINERS
fi
if [ "${KEEP_CONTAINERS}" == "**All**" ]; then
KEEP_CONTAINERS="."
fi
if [ "${KEEP_CONTAINERS_NAMED}" == "**None**" ]; then
unset KEEP_CONTAINERS_NAMED
fi
if [ "${KEEP_CONTAINERS_NAMED}" == "**All**" ]; then
KEEP_CONTAINERS_NAMED="."
fi
if [ "${LOOP}" != "false" ]; then
LOOP=true
fi
if [ "${DEBUG}" == "0" ]; then
unset DEBUG
fi
if [ $DEBUG ]; then echo DEBUG ENABLED; fi
echo "=> Run the clean script every ${CLEAN_PERIOD} seconds and delay ${DELAY_TIME} seconds to clean."
trap '{ echo "User Interupt."; exit 1; }' SIGINT
trap '{ echo "SIGTERM received, exiting."; exit 0; }' SIGTERM
while [ 1 ]
do
if [ $DEBUG ]; then echo DEBUG: Starting loop; fi
# Cleanup unused volumes
if [[ $(docker version --format '{{(index .Server.Version)}}' | grep -E '^[01]\.[012345678]\.') ]]; then
echo "=> Removing unused volumes using 'docker-cleanup-volumes.sh' script"
/docker-cleanup-volumes.sh
else
echo "=> Removing unused volumes using native 'docker volume' command"
for volume in $(docker volume ls -qf dangling=true); do
echo "Deleting ${volume}"
docker volume rm "${volume}"
done
fi
IFS='
'
# Cleanup exited/dead containers
echo "=> Removing exited/dead containers"
EXITED_CONTAINERS_IDS="`docker ps -a -q -f status=exited -f status=dead | xargs echo`"
for CONTAINER_ID in $EXITED_CONTAINERS_IDS; do
CONTAINER_IMAGE=$(docker inspect --format='{{(index .Config.Image)}}' $CONTAINER_ID)
CONTAINER_NAME=$(docker inspect --format='{{(index .Name)}}' $CONTAINER_ID)
if [ $DEBUG ]; then echo "DEBUG: Check container image $CONTAINER_IMAGE named $CONTAINER_NAME"; fi
keepit=0
checkPatterns "${KEEP_CONTAINERS}" "${CONTAINER_IMAGE}" $keepit
keepit=$?
checkPatterns "${KEEP_CONTAINERS_NAMED}" "${CONTAINER_NAME}" $keepit
keepit=$?
if [[ $keepit -eq 0 ]]; then
echo "Removing stopped container $CONTAINER_ID"
docker rm -v $CONTAINER_ID
fi
done
unset CONTAINER_ID
echo "=> Removing unused images"
# Get all containers in "created" state
rm -f CreatedContainerIdList
docker ps -a -q -f status=created | sort > CreatedContainerIdList
# Get all image ID
ALL_LAYER_NUM=$(docker images -a | tail -n +2 | wc -l)
docker images -q --no-trunc | sort -o ImageIdList
CONTAINER_ID_LIST=$(docker ps -aq --no-trunc)
# Get Image ID that is used by a containter
rm -f ContainerImageIdList
touch ContainerImageIdList
for CONTAINER_ID in ${CONTAINER_ID_LIST}; do
LINE=$(docker inspect ${CONTAINER_ID} | grep "\"Image\": \"\(sha256:\)\?[0-9a-fA-F]\{64\}\"")
IMAGE_ID=$(echo ${LINE} | awk -F '"' '{print $4}')
echo "${IMAGE_ID}" >> ContainerImageIdList
done
sort ContainerImageIdList -o ContainerImageIdList
# Remove the images being used by containers from the delete list
comm -23 ImageIdList ContainerImageIdList > ToBeCleanedImageIdList
# Remove those reserved images from the delete list
if [ -n "${KEEP_IMAGES}" ]; then
rm -f KeepImageIdList
touch KeepImageIdList
# This looks to see if anything matches the regexp
docker images --no-trunc | (
while read repo tag image junk; do
keepit=0
if [ $DEBUG ]; then echo "DEBUG: Check image $repo:$tag"; fi
for PATTERN in $(echo ${KEEP_IMAGES} | tr "," "\n"); do
if [[ -n "$PATTERN" && "${repo}:${tag}" = $PATTERN* ]]; then
if [ $DEBUG ]; then echo "DEBUG: Matches $PATTERN"; fi
keepit=1
else
if [ $DEBUG ]; then echo "DEBUG: No match for $PATTERN"; fi
fi
done
if [[ $keepit -eq 1 ]]; then
if [ $DEBUG ]; then echo "DEBUG: Marking image $repo:$tag to keep"; fi
echo $image >> KeepImageIdList
fi
done
)
# This explicitly looks for the images specified
arr=$(echo ${KEEP_IMAGES} | tr "," "\n")
for x in $arr
do
if [ $DEBUG ]; then echo "DEBUG: Identifying image $x"; fi
docker inspect $x 2>/dev/null| grep "\"Id\": \"\(sha256:\)\?[0-9a-fA-F]\{64\}\"" | head -1 | awk -F '"' '{print $4}' >> KeepImageIdList
done
sort KeepImageIdList -o KeepImageIdList
comm -23 ToBeCleanedImageIdList KeepImageIdList > ToBeCleanedImageIdList2
mv ToBeCleanedImageIdList2 ToBeCleanedImageIdList
fi
# Wait before cleaning containers and images
echo "=> Waiting ${DELAY_TIME} seconds before cleaning"
sleep ${DELAY_TIME} & wait
# Remove created containers that haven't managed to start within the DELAY_TIME interval
rm -f CreatedContainerToClean
comm -12 CreatedContainerIdList <(docker ps -a -q -f status=created | sort) > CreatedContainerToClean
if [ -s CreatedContainerToClean ]; then
echo "=> Start to clean $(cat CreatedContainerToClean | wc -l) created/stuck containers"
if [ $DEBUG ]; then echo "DEBUG: Removing unstarted containers"; fi
docker rm -v $(cat CreatedContainerToClean)
fi
# Remove images being used by containers from the delete list again. This prevents the images being pulled from deleting
CONTAINER_ID_LIST=$(docker ps -aq --no-trunc)
rm -f ContainerImageIdList
touch ContainerImageIdList
for CONTAINER_ID in ${CONTAINER_ID_LIST}; do
LINE=$(docker inspect ${CONTAINER_ID} | grep "\"Image\": \"\(sha256:\)\?[0-9a-fA-F]\{64\}\"")
IMAGE_ID=$(echo ${LINE} | awk -F '"' '{print $4}')
echo "${IMAGE_ID}" >> ContainerImageIdList
done
sort ContainerImageIdList -o ContainerImageIdList
comm -23 ToBeCleanedImageIdList ContainerImageIdList > ToBeCleaned
# Remove Images
if [ -s ToBeCleaned ]; then
echo "=> Start to clean $(cat ToBeCleaned | wc -l) images"
docker rmi -f $(cat ToBeCleaned) 2>/dev/null
(( DIFF_LAYER=${ALL_LAYER_NUM}- $(docker images -a | tail -n +2 | wc -l) ))
(( DIFF_IMG=$(cat ImageIdList | wc -l) - $(docker images | tail -n +2 | wc -l) ))
if [ ! ${DIFF_LAYER} -gt 0 ]; then
DIFF_LAYER=0
fi
if [ ! ${DIFF_IMG} -gt 0 ]; then
DIFF_IMG=0
fi
echo "=> Done! ${DIFF_IMG} images and ${DIFF_LAYER} layers have been cleaned."
else
echo "No images need to be cleaned"
fi
rm -f ToBeCleanedImageIdList ContainerImageIdList ToBeCleaned ImageIdList KeepImageIdList
# Run forever or exit after the first run depending on the value of $LOOP
[ "${LOOP}" == "true" ] || break
echo "=> Next clean will be started in ${CLEAN_PERIOD} seconds"
sleep ${CLEAN_PERIOD} & wait
done