Skip to content

Commit 6ec3fc4

Browse files
committed
Avoid parsing global or image-specific args
Among other things.
1 parent 4e40b99 commit 6ec3fc4

File tree

3 files changed

+192
-23
lines changed

3 files changed

+192
-23
lines changed

Dockerfile

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
ARG DOCKER_VERSION="latest"
2+
FROM docker:${DOCKER_VERSION} AS test
3+
4+
# Install APK deps
5+
RUN apk add --no-cache bash
6+
7+
# Install dond-shim
8+
ARG DOCKER_PATH="/usr/local/bin/docker"
9+
RUN mv -f "${DOCKER_PATH}" "${DOCKER_PATH}.orig"
10+
COPY docker "${DOCKER_PATH}"
11+
12+
# Create fixtures
13+
RUN mkdir -p /test && \
14+
echo test | tee /test/only-inside-container
15+
16+
# Set default stage
117
FROM felipecrs/fixdockergid:latest
218

319
USER root
@@ -7,6 +23,3 @@ RUN mv -f "${DOCKER_PATH}" "${DOCKER_PATH}.orig"
723
COPY docker "${DOCKER_PATH}"
824

925
USER rootless
10-
11-
# Create fixtures
12-
RUN echo test | tee /home/rootless/only-inside-container

docker

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
set -euo pipefail
44

5+
if [[ "${DOND_SHIM_DEBUG:-false}" == true ]]; then
6+
set -x
7+
fi
8+
59
function get_container_id() {
610
local cpuset_output
711
cpuset_output=$(head -1 /proc/self/cpuset)
@@ -74,14 +78,107 @@ function fix_volume_arg() {
7478
volume_arg="${source}:${destination}"
7579
}
7680

81+
function get_docker_options_with_value() {
82+
local -n target_array="${1}"
83+
shift 1
84+
local command=("${@}")
85+
86+
local help_output
87+
help_output="$(docker.orig "${command[@]}" --help)"
88+
89+
readarray -t help_lines <<<"${help_output}"
90+
target_array=()
91+
for line in "${help_lines[@]}"; do
92+
# second group is the short option (optional)
93+
# third group is the long option
94+
if [[ "${line}" =~ ^[[:space:]]+((-[a-zA-Z]),[[:space:]])?(--[a-z0-9-]+)[[:space:]][a-z]+[[:space:]]+.*$ ]]; then
95+
if [[ -n "${BASH_REMATCH[2]}" ]]; then
96+
target_array+=("${BASH_REMATCH[2]}")
97+
fi
98+
target_array+=("${BASH_REMATCH[3]}")
99+
fi
100+
done
101+
}
102+
103+
options_with_value=()
104+
get_docker_options_with_value options_with_value
105+
77106
original_args=("$@")
78-
fixed_args=()
79107

80-
# TODO: only piggyback on docker run, container run, create and container create
108+
skip_next=false
109+
parsing="global"
110+
global_args=()
111+
found_first_global_positional=false
112+
command_args=()
113+
image_args=()
114+
for i in "${!original_args[@]}"; do
115+
arg="${original_args[${i}]}"
116+
117+
if [[ "${parsing}" == "global" ]]; then
118+
global_args+=("${arg}")
119+
120+
if [[ "${skip_next}" == true ]]; then
121+
skip_next=false
122+
continue
123+
fi
124+
125+
if [[ "${arg}" == "-"* ]]; then
126+
if [[ "${found_first_global_positional}" == false ]]; then
127+
for option_with_value in "${options_with_value[@]}"; do
128+
if [[ "${arg}" == "${option_with_value}" ]]; then
129+
skip_next=true
130+
continue
131+
fi
132+
done
133+
fi
134+
continue
135+
fi
136+
137+
if [[ "${arg}" == "run" || "${arg}" == "create" ]]; then
138+
options_with_value=()
139+
get_docker_options_with_value options_with_value "${arg}"
140+
parsing="command"
141+
elif [[ "${arg}" == "container" ]]; then
142+
found_first_global_positional=true
143+
true
144+
else
145+
# Skip if command is not run, create, container run, or container create
146+
if [[ "${DOND_SHIM_PRINT_COMMAND:-false}" == true ]]; then
147+
echo docker.orig "${original_args[@]}"
148+
exit 0
149+
else
150+
exec docker.orig "${original_args[@]}"
151+
fi
152+
fi
153+
elif [[ "${parsing}" == "command" ]]; then
154+
command_args+=("${arg}")
155+
156+
if [[ "${skip_next}" == true ]]; then
157+
skip_next=false
158+
continue
159+
fi
160+
161+
if [[ "${arg}" == "-"* ]]; then
162+
for option_with_value in "${options_with_value[@]}"; do
163+
if [[ "${arg}" == "${option_with_value}" ]]; then
164+
skip_next=true
165+
continue
166+
fi
167+
done
168+
continue
169+
fi
170+
171+
# If this is reached, then the first positional argument has been found
172+
parsing="image"
173+
elif [[ "${parsing}" == "image" ]]; then
174+
image_args+=("${arg}")
175+
fi
176+
done
81177

178+
fixed_args=()
82179
extra_args=()
83180
fix_next_arg=false
84-
for arg in "${original_args[@]}"; do
181+
for arg in "${command_args[@]}"; do
85182
if [[ "${fix_next_arg}" == true ]]; then
86183
fix_next_arg=false
87184
volume_arg="${arg}"
@@ -100,4 +197,10 @@ for arg in "${original_args[@]}"; do
100197
extra_args=()
101198
done
102199

103-
exec docker.orig "${fixed_args[@]}"
200+
final_command=(docker.orig "${global_args[@]}" "${fixed_args[@]}" "${image_args[@]}")
201+
202+
if [[ "${DOND_SHIM_PRINT_COMMAND:-false}" == true ]]; then
203+
echo "${final_command[@]}"
204+
else
205+
exec "${final_command[@]}"
206+
fi

test.sh

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,78 @@
11
#!/bin/bash
22

3-
set -euxo pipefail
3+
set -euo pipefail
44

5-
image_id="$(docker build --quiet .)"
5+
if [[ "${DEBUG:-false}" == true ]]; then
6+
set -x
7+
export DOND_SHIM_DEBUG=true
8+
fi
69

7-
# shellcheck disable=SC2312
8-
docker_args=(docker run --rm --user "$(id -u):$(id -g)" --volume /var/run/docker.sock:/var/run/docker.sock)
10+
# Set docker versions from args or use defaults
11+
if [[ $# -eq 0 ]]; then
12+
docker_versions=("18.09" "19.03" "20.10" "23" "24" latest)
13+
else
14+
docker_versions=("$@")
15+
fi
916

10-
# Check if docker on docker is working
11-
"${docker_args[@]}" "${image_id}" docker version >/dev/null
17+
for docker_version in "${docker_versions[@]}"; do
18+
echo "Testing with docker version: ${docker_version}"
1219

13-
# Check if mounting an volume from the container gets fixed
14-
"${docker_args[@]}" "${image_id}" docker run --rm --volume /home/rootless/only-inside-container:/only-inside-container ubuntu:latest grep "^test$" /only-inside-container >/dev/null
15-
"${docker_args[@]}" "${image_id}" docker run --rm --volume=/home/rootless/only-inside-container:/only-inside-container ubuntu:latest grep "^test$" /only-inside-container >/dev/null
20+
image_id="$(docker build --target test --build-arg "DOCKER_VERSION=${docker_version}" --quiet .)"
1621

17-
# Check if mounting a volume which is already a volume gets fixed
18-
"${docker_args[@]}" --volume "${PWD}:/wd" "${image_id}" docker run --rm --volume /wd:/wd ubuntu:latest grep "^test$" /wd/testfile >/dev/null
22+
# shellcheck disable=SC2312
23+
docker_args=(docker run --rm --env DOND_SHIM_DEBUG --entrypoint= --volume /var/run/docker.sock:/var/run/docker.sock)
1924

20-
# Same as above but for a file within the volume
21-
"${docker_args[@]}" --volume "${PWD}:/wd" "${image_id}" docker run --rm --volume /wd/testfile:/wd/testfile ubuntu:latest grep "^test$" /wd/testfile >/dev/null
25+
echo "Do not change global options or after the image"
26+
"${docker_args[@]}" --env DOND_SHIM_PRINT_COMMAND=true --volume "${PWD}:/wd" "${image_id}" \
27+
docker --host test run --volume /wd:/wd alpine --volume /wd:/wd |
28+
grep --quiet "^docker.orig --host test run --volume ${PWD}:/wd alpine --volume /wd:/wd$"
2229

23-
# Volumes inside volumes
24-
"${docker_args[@]}" --volume "${PWD}/testfile:/home/rootless/testfile" "${image_id}" docker run --rm --volume /home/rootless:/wd ubuntu:latest grep "^test$" /wd/testfile >/dev/null
25-
"${docker_args[@]}" --volume "${PWD}/testfile:/home/rootless/testfile" --volume "${PWD}/testfile:/home/rootless/testfile2" "${image_id}" docker run --rm --volume /home/rootless:/wd ubuntu:latest bash -c 'grep "^test$" /wd/testfile && grep "^test$" /wd/testfile2 && grep "^test$" /wd/only-inside-container' >/dev/null
30+
echo "Same but for container run"
31+
"${docker_args[@]}" --env DOND_SHIM_PRINT_COMMAND=true --volume "${PWD}:/wd" "${image_id}" \
32+
docker --host test container run --volume /wd:/wd alpine --volume /wd:/wd |
33+
grep --quiet "^docker.orig --host test container run --volume ${PWD}:/wd alpine --volume /wd:/wd$"
34+
35+
echo "Same but for create"
36+
"${docker_args[@]}" --env DOND_SHIM_PRINT_COMMAND=true --volume "${PWD}:/wd" "${image_id}" \
37+
docker --host test create --volume /wd:/wd alpine --volume /wd:/wd |
38+
grep --quiet "^docker.orig --host test create --volume ${PWD}:/wd alpine --volume /wd:/wd$"
39+
40+
echo "Same but container create"
41+
"${docker_args[@]}" --env DOND_SHIM_PRINT_COMMAND=true --volume "${PWD}:/wd" "${image_id}" \
42+
docker --host test container create --volume /wd:/wd alpine --volume /wd:/wd |
43+
grep --quiet "^docker.orig --host test container create --volume ${PWD}:/wd alpine --volume /wd:/wd$"
44+
45+
echo "Do not do anything for other commands"
46+
"${docker_args[@]}" --env DOND_SHIM_PRINT_COMMAND=true --volume "${PWD}:/wd" "${image_id}" \
47+
docker --host test whatever --volume /wd:/wd alpine --volume /wd:/wd |
48+
grep --quiet "^docker.orig --host test whatever --volume /wd:/wd alpine --volume /wd:/wd$"
49+
50+
echo "Check if docker on docker is working"
51+
"${docker_args[@]}" "${image_id}" \
52+
docker version >/dev/null
53+
54+
echo "Check if mounting an volume from the container gets fixed"
55+
"${docker_args[@]}" "${image_id}" \
56+
docker run --rm --volume /test/only-inside-container:/only-inside-container ubuntu:latest grep "^test$" /only-inside-container >/dev/null
57+
58+
echo "Same but with equals sign"
59+
"${docker_args[@]}" "${image_id}" \
60+
docker run --rm --volume=/test/only-inside-container:/only-inside-container ubuntu:latest grep "^test$" /only-inside-container >/dev/null
61+
62+
echo "Check if mounting a volume which is already a volume gets fixed"
63+
"${docker_args[@]}" --volume "${PWD}:/wd" "${image_id}" \
64+
docker run --rm --volume /wd:/wd ubuntu:latest grep "^test$" /wd/testfile >/dev/null
65+
66+
echo "Same as above but for a file within the volume"
67+
"${docker_args[@]}" --volume "${PWD}:/wd" "${image_id}" \
68+
docker run --rm --volume /wd/testfile:/wd/testfile ubuntu:latest grep "^test$" /wd/testfile >/dev/null
69+
70+
echo "Check if mounting a volume which contains another volume adds all proper volumes"
71+
"${docker_args[@]}" --volume "${PWD}/testfile:/test/testfile" "${image_id}" \
72+
docker run --rm --volume /test:/wd ubuntu:latest grep "^test$" /wd/testfile >/dev/null
73+
74+
echo "Same as above but for multiple files under different volumes"
75+
"${docker_args[@]}" --volume "${PWD}/testfile:/test/testfile" --volume "${PWD}/testfile:/test/testfile2" "${image_id}" \
76+
docker run --rm --volume /test:/wd ubuntu:latest bash -c 'grep "^test$" /wd/testfile && grep "^test$" /wd/testfile2 && grep "^test$" /wd/only-inside-container' >/dev/null
77+
78+
done

0 commit comments

Comments
 (0)