diff --git a/Makefile b/Makefile
index a86621dec150c7ffc7331c7ccf8525dc70d31874..f926c3d2b3ed29fb6d439e1127f2bce952f5d18a 100644
--- a/Makefile
+++ b/Makefile
@@ -8,11 +8,14 @@ LDFLAGS := -luring -pthread -lrt
 # CFLAGS := -Werror -Wall -g -O3
 CFLAGS := -Werror -Wall -g -O0
 
-.PHONY: all clean eval
+.PHONY: all clean eval docker-eval
 
 eval: all
 	@for syscall in $(SYSCALLS); do echo -n "$$syscall " ; ./bench-$$syscall; done
 
+docker-eval:
+	./docker.sh make eval
+
 all: $(OBJ)
 
 define generateTargets
diff --git a/docker.sh b/docker.sh
new file mode 100755
index 0000000000000000000000000000000000000000..07ced4a33186c3bde45c3a153251f25e1dcf1377
--- /dev/null
+++ b/docker.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+# The directory of this script is also the project's root directory.
+ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+
+IMAGE=$(sed --regexp-extended --quiet 's;^image: "([^"]*)"$;\1;p' "${ROOT}/.gitlab-ci.yml")
+
+docker run \
+	   --volume="${ROOT}:${ROOT}" \
+	   --interactive \
+	   --tty \
+	   --security-opt seccomp=.docker-seccomp-profile.json \
+	   --env USER_ID="${UID}" \
+	   --env GROUP_ID="$(id -g ${USER})" \
+	   "${IMAGE}" \
+	   "${ROOT}/tools/docker-prepare" "${ROOT}" $@
diff --git a/tools/docker-prepare b/tools/docker-prepare
new file mode 100755
index 0000000000000000000000000000000000000000..ca7d8a504269065a4131efdae889fc9bd39d1fe6
--- /dev/null
+++ b/tools/docker-prepare
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+useradd -u "${USER_ID}" -o -m user
+groupmod -g "${GROUP_ID}" user
+
+if [[ ! -f "/usr/lib/libomp.so" ]] && [[ -f /usr/lib/llvm-12/lib/libomp.so ]]; then
+	ln -s /usr/lib/llvm-12/lib/libomp.so /usr/lib
+fi
+
+ln -s /usr/bin/perf_5.10 /usr/bin/perf
+
+OUTSIDE_ROOT="${1}"
+shift
+
+cd "${OUTSIDE_ROOT}"
+
+# shellcheck disable=SC2068
+exec sudo -u user $@