forked from radareorg/radare2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocker_build_alpine_image.sh
executable file
·330 lines (296 loc) · 7.29 KB
/
docker_build_alpine_image.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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#!/bin/sh
# r2docker
# ========
#
# Requires ~140MB of free disk space
#
# Build docker image with:
# $ ./sys/docker_build_alpine_image.sh
#
# Run the docker image:
#
# $ r2d() {
# local rm
# case "$1" in
# "-r"|"--rm") rm="--rm" && shift ;;
# esac
# docker run --cap-drop=ALL --cap-add=SYS_PTRACE -i \
# `--name r2_$(date +%F_%H%M%S%N) $rm -tv $(pwd):/r2 \
# r2_alpine:latest $@
# }
# $ r2d # Optional --rm
#
# Once you quit the session, get the container id with something like:
#
# $ containerid="$(docker ps -a | awk '/r2_alpine/ {print $NF}')"
#
# To get into that shell again just type:
#
# $ docker start -ai $containerid
#
# To share those images:
#
# $ docker export $containerid | xz >container.tar.xz
# $ xz -d <container.tar.xz | docker import -
#
# When finished:
#
# $ docker rm -f $containerid
#
# If you are unwilling to debug a program within Docker, remove
# --cap-add=SYS_PTRACE from the r2d function. If you need sudo to
# install more packages within Docker, remove --cap-drop=ALL from the
# r2d function.
### Helpers begin
checkdeps() {
for d in curl docker jq; do
if [ -z "$(command -v "$d")" ]; then
echo "[!] $d is not installed"
exit 128
fi
done
unset d
}
long_opt() {
arg=""
shift="0"
case "$1" in
"--"*"="*) arg="${1#*=}"; [ -n "$arg" ] || usage 127 ;;
*) shift="1"; shift; [ $# -gt 0 ] || usage 127; arg="$1" ;;
esac
echo "$arg"
unset arg
return $shift
}
### Helpers end
cleanup() {
rm -rf "$tmp_docker_dir"
[ "${1:-0}" -eq 0 ] || exit "$1"
}
usage() {
cat <<EOF
Usage: ${0##*/} [OPTIONS]
Build a Radare2 docker image that uses local user/group IDs.
Options:
-b, --branch=BRANCH Use specified radare2 branch (default:
master)
-h, --help Display this help message
--node=VERSION Use specified Node.js version (default: 10)
-n, --npm=VERSION Use specified version of r2pipe npm binding
(default: newest)
-p, --py=VERSION Use specified version of r2pipe python
binding (default: newest)
EOF
exit "$1"
}
args=""
unset help r2pipe_npm r2pipe_py
github="https://github.com/radareorg/radare2.git"
r2branch="master"
# Check for missing dependencies
checkdeps
# Parse command line options
while [ $# -gt 0 ]; do
case "$1" in
"--") shift && args="$args${args:+ }$*" && break ;;
"-b"|"--branch"*) r2branch="$(long_opt "$@")" || shift ;;
"-h"|"--help") help="true" ;;
"-n"|"--npm"*) r2pipe_npm="@$(long_opt "$@")" || shift ;;
"-p"|"--py"*) r2pipe_py="==$(long_opt "$@")" || shift ;;
*) args="$args${args:+ }$1" ;;
esac
shift
done
[ -z "$args" ] || set -- "$args"
# Check for valid params
[ -z "$help" ] || usage 0
[ $# -eq 0 ] || usage 1
if [ "`uname`" = Linux ]; then
if [ "$(id -u)" -ne 0 ] && id -Gn | grep -qvw "docker"; then
echo "[!] You are not part of the docker group"
exit 2
fi
fi
trap "cleanup 126" INT
# Create Dockerfile
tmp_docker_dir=".docker_alpine"
gid="$(id -g)"
gname="$(id -gn)"
r2commit="$(
curl -Ls \
"http://api.github.com/repos/radare/radare2/commits/$r2branch" | \
jq -cMrS ".sha"
)"
uid="$(id -u)"
uname="$(id -nu)"
mkdir -p $tmp_docker_dir
cat >$tmp_docker_dir/Dockerfile <<EOF
# Using super tiny alpine base image
FROM alpine:latest
# Install bash b/c it's better
RUN apk upgrade && apk add bash
# Bash is better than sh
SHELL ["/bin/bash", "-c"]
# Build radare2 in a volume to minimize space used by build
VOLUME ["/mnt"]
# All one RUN layer, splitting into 3 increases size to ~360MB, wtf
# 1. Install dependencies
# 2. Install Node.js and Python bindings (do we need these?)
# 3. Create id and gid to match current local user
# 4. Add new user to sudoers without password
# 5. Add some convenient aliases to .bashrc
# 6. Clone and install radare2
# 7. Clean up unnecessary files and packages
RUN set -o pipefail && \
( \
apk upgrade && \
apk add \
g++ \
gcc \
git \
libc6-compat \
linux-headers \
make \
ncurses-libs \
nodejs-current \
npm \
py2-pip \
shadow \
sudo \
) && ( \
npm install -g --unsafe-perm "r2pipe$r2pipe_npm" && \
pip install --upgrade pip && \
pip install r2pipe$r2pipe_py \
) && ( \
[ "$gname" != "root" ] || \
( \
echo "alias la=\"\\ls -AF\"" >>/root/.bashrc && \
echo "alias ll=\"\\ls -Fhl\"" >>/root/.bashrc && \
echo "alias ls=\"\\ls -F\"" >>/root/.bashrc && \
echo "alias q=\"exit\"" >>/root/.bashrc \
) \
) && ( \
[ "$gname" = "root" ] || \
( \
groupadd -f $gname && \
(groupmod -g $gid $gname 2>/dev/null || true) && \
useradd -g $gid -mou $uid $uname && \
echo "$uname ALL=(ALL) NOPASSWD: ALL" \
>/etc/sudoers.d/$uname && \
echo "alias la=\"\\ls -AF\"" >>/home/$uname/.bashrc && \
echo "alias ll=\"\\ls -Fhl\"" >>/home/$uname/.bashrc && \
echo "alias ls=\"\\ls -F\"" >>/home/$uname/.bashrc && \
echo "alias q=\"exit\"" >>/home/$uname/.bashrc \
) \
) && ( \
cd /mnt && \
git clone -b $r2branch --depth 1 $github && \
cd radare2 && \
git checkout $r2commit && \
./sys/install.sh && \
make install \
) && ( \
apk del --purge -r \
g++ \
gcc \
linux-headers \
make \
npm \
py2-pip && \
rm -rf /tmp/* /var/cache/apk/* /var/tmp/* \
)
# Initialize env
USER $(id -nu)
WORKDIR /r2
# Setup r2pm
RUN set -o pipefail && \
r2pm init && \
r2pm update
CMD ["/bin/bash"]
EOF
# Tag old images
echo "[*] Tagging any old r2_alpine images"
docker images | awk '{print $1":"$3}' | while read -r tag; do
case "$tag" in
"r2_alpine:"*) docker image tag "${tag#*:}" "$tag" ;;
esac
done
unset tag
findbase="$(
docker images | grep -E "^(docker\.io\/)?alpine +latest "
)"
# Build image (may take a while)
echo "[*] Building image..."
echo "[*] This may take a long time..."
# Pull newest base image and build r2_alpine image
docker pull alpine:latest
(
if [ ! -d "$tmp_docker_dir" ]; then
echo "$tmp_docker_dir not found"
fi
cd $tmp_docker_dir || exit 3
# shellcheck disable=SC2154
docker build \
${http_proxy:+--build-arg http_proxy=$http_proxy} \
${https_proxy:+--build-arg https_proxy=$https_proxy} \
-t r2_alpine:latest .
)
# Only remove base image if it didn't already exist
[ -n "$findbase" ] || docker rmi alpine:latest
echo "[*] done"
old_base="^(docker\.io\/)?alpine +<none>"
old_r2="^r2_alpine +[^l ]"
found="$(
docker images | grep -E "($old_base)|($old_r2)"
)"
if [ -n "$found" ]; then
# List old images
echo
echo "[*] Old images:"
docker images | head -n 1
docker images | grep -E "($old_base)|($old_r2)" | \
while read -r line; do
echo "$line"
done
unset line
# Prompt to remove old images
unset remove
echo
while :; do
echo "Remove old images (y/N/q)?"
read -r ans
echo
case "$ans" in
""|"n"|"N"|"q"|"Q") break ;;
"y"|"Y") remove="true"; break ;;
*) echo "Invalid choice" ;;
esac
done
if [ -n "$remove" ]; then
# Remove old images
docker images | awk "/$old_r2/ {print \$1\":\"\$3}" | \
while read -r tag; do
docker rmi "$tag"
done
unset tag
docker images | awk "/$old_base/ {print \$3}" | \
while read -r id; do
docker rmi "$id"
done
unset id
fi
fi
unset found
cleanup 0
cat <<EOF
It's suggested you add something like the following to your ~/.bashrc:
r2d() {
local rm
case "\$1" in
"-r"|"--rm") rm="--rm" && shift ;;
esac
docker run --cap-drop=ALL --cap-add=SYS_PTRACE -i \\
--name r2_\$(date +%F_%H%M%S%N) \$rm -tv \$(pwd):/r2 \\
r2_alpine:latest \$@
}
EOF