This repository has been archived by the owner on Jul 8, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ddo
executable file
·173 lines (145 loc) · 5.07 KB
/
ddo
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
#!/bin/bash
# see https://github.com/benzaita/docker-do
set -e
verbose=0
function die_usage {
echo "
Usage: $0 [-h | --help | COMMAND] [-- OPTIONS FOR DOCKER RUN]
Environment variables:
DDO_VERBOSE=1 to increase verbosity
DDO_RUN_WITH_MY_UID=1 to invoke 'docker run' with '-u CURRENT_UID'
"
exit 1
}
function printv {
if [[ $verbose -eq 1 ]]; then
echo "$0: $*"
fi
}
verbose=$DDO_VERBOSE
# aggregate all arguments until '--' as the command
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
die_usage
fi
while [[ $# -gt 0 ]] && [[ "$1" != '--' ]]; do
cmd="$cmd $1"
shift 1
done
# anything after '--' is for `docker run`
if [[ "$1" == '--' ]]; then
shift 1
docker_run_args="$*"
fi
# command compatabile commands
if readlink -f . > /dev/null 2>&1 ; then
readlink_cmd=$(which readlink)
else
if greadlink -f . > /dev/null 2>&1 ; then
readlink_cmd=$(which greadlink)
else
echo "Cannot find a valid 'readlink -f' command"
exit 1
fi
fi
if md5sum --version > /dev/null 2>&1 ; then
md5_cmd=$(which md5sum)
else
if md5 -x > /dev/null 2>&1 ; then
md5_cmd="$(which md5) -r"
else
echo "Cannot find a valid 'md5sum' or 'md5' command"
exit 1
fi
fi
# find the nearest Dockerfile up the tree
Dockerfile_dir=$(pwd)
while [[ "$Dockerfile_dir" != "/" ]]; do
if [[ -f "$Dockerfile_dir/Dockerfile" ]]; then
break
else
Dockerfile_dir=$(dirname "$Dockerfile_dir")
fi
done
if [[ "$Dockerfile_dir" == "/" ]]; then
echo >&2 "$0: could not find Dockerfile anywhere up this tree"
exit 1
fi
printv "found Dockerfile in $Dockerfile_dir"
# base_dir is where we found the Dockerfile
base_dir=$($readlink_cmd -f $Dockerfile_dir)
do_dir=$base_dir/.do
# find where we are relative to $base_dir
# e.g. if $base_dir is "/tmp/" and the current working-dir is "/tmp/a"
# then we want to get just "a"
abs_wd=$($readlink_cmd -f $(pwd))
rel_wd=$(python -c "import os.path; print os.path.relpath(\"$abs_wd\", \"$base_dir\")")
# build the command to run inside the docker container
if [[ "$cmd" != "" ]]; then
cmd="cd $rel_wd && $cmd"
fi
# find out the current user id
user_id=$(id -u)
# create $do_dir if necessary
mkdir -p $do_dir
# decide is `docker build` is necessary
build_needed=1
if [[ -f $do_dir/image_name ]]; then # did we previously build?
image_name=$(cat $do_dir/image_name)
# we have an image name, but does it exist?
if docker inspect $image_name >/dev/null 2>/dev/null; then
# do we have the MD5 of the original Dockerfile?
if [[ -f $do_dir/dockerfile_md5 ]]; then
orig_dockerfile_md5=$([[ -f $do_dir/dockerfile_md5 ]] && cat $do_dir/dockerfile_md5)
curr_dockerfile_md5=$($md5_cmd $Dockerfile_dir/Dockerfile | awk '{print $1}')
# did the Dockerfile change since it was built?
if [[ "$orig_dockerfile_md5" == "$curr_dockerfile_md5" ]]; then
printv 'Dockerfile did not change since we built the image - no need to do `docker build`'
build_needed=0
else
printv 'Dockerfile changed since we last did `docker build` - will remove and rebuild'
fi
else
# we don't have the original Dockerfile's MD5 (maybe $do_dir was
# created with an old version of ddo) - be on the safe side and build
printv "could not find original Dockerfile's MD5 ($do_dir/dockerfile_md5) - will do \`docker build\`"
fi
else
printv 'previously built image ($image_name) does not exist - will do `docker build`'
fi
fi
# build if needed
if [[ $build_needed -eq 1 ]]; then
# remove previously built image
if [[ "$image_name" != "" ]]; then
rm_cmd="docker rmi $image_name"
printv "running '$rm_cmd'"
eval $rm_cmd || echo "failed to remove old image ($image_name)"
fi
# build new image
cur_dir_name=$(basename $(dirname $($readlink_cmd -f $0)))
unique_id=$($md5_cmd $Dockerfile_dir/Dockerfile | awk '{print $1}')
image_name=$(echo $cur_dir_name-$unique_id | tr '[:upper:]' '[:lower:]' | tr -d -c '[a-z0-9-_.]')
curr_dockerfile_md5=$($md5_cmd $Dockerfile_dir/Dockerfile | awk '{print $1}')
printv "running \`docker build\` in $base_dir"
cd $base_dir
docker build -t $image_name .
cd -
echo $image_name > $do_dir/image_name
echo $curr_dockerfile_md5 > $do_dir/dockerfile_md5
fi
# abort if the docker image does not have
# ENTRYPOINT ["/bin/sh", "-c"]
entry_point=$(docker inspect -f '{{.Config.Entrypoint}}' $image_name)
if [[ $(echo $entry_point | grep -cF /bin/sh) -eq 0 ]]; then
echo >&2 "$0: Dockerfile ENTRYPOINT must be set to: [\"/bin/sh\", \"-c\"]; was '$entry_point'. aborting"
exit 1
fi
# build "docker run" command
docker_run_cmd="docker run --rm"
if [[ "$DDO_RUN_WITH_MY_UID" == "1" ]]; then
docker_run_cmd="$docker_run_cmd -u $user_id"
fi
docker_run_cmd="$docker_run_cmd -v $base_dir:/workspace"
docker_run_cmd="$docker_run_cmd $docker_run_args $image_name \"$cmd\""
printv "running: $docker_run_cmd"
eval $docker_run_cmd