From 0f4328e1713dfea73e82c91a3ca194d734416fe3 Mon Sep 17 00:00:00 2001 From: Jonas Kohl Date: Thu, 7 Nov 2024 17:59:09 +0100 Subject: Dockerize whole application --- Dockerfile | 22 +++++++++++ compile-and-run.sh | 24 ++++++------ compose.yml | 7 ++++ entrypoint.sh | 6 +++ generate-status-object.php | 30 -------------- httpd-foreground | 7 ++++ httpd.conf | 97 ++++++++++++++++++++++++++++++++++++++++++++++ public/index.php | 61 +++++++++++++++++++++++++---- 8 files changed, 204 insertions(+), 50 deletions(-) create mode 100644 Dockerfile create mode 100644 compose.yml create mode 100644 entrypoint.sh delete mode 100644 generate-status-object.php create mode 100644 httpd-foreground create mode 100644 httpd.conf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..387023f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM docker:27-dind AS apache +USER root +RUN apk update && \ + apk add --no-cache \ + bash \ + coreutils \ + su-exec \ + apache2 \ + php83-apache2 \ + php83-session +RUN adduser -D apache2 && \ + addgroup apache2 docker +RUN mkdir -p /root/.docker && \ + chmod -R 0777 /root/.docker +RUN chmod 4755 /sbin/su-exec +COPY --chmod=777 httpd-foreground /usr/local/bin/ +COPY --chmod=777 entrypoint.sh /usr/local/bin/ +COPY --chmod=777 . /opt/application +COPY httpd.conf /etc/apache2/httpd.conf +ENV IS_IN_DOCKER=1 +EXPOSE 80 +CMD ["/usr/local/bin/entrypoint.sh"] diff --git a/compile-and-run.sh b/compile-and-run.sh index 64bacb1..423206e 100755 --- a/compile-and-run.sh +++ b/compile-and-run.sh @@ -2,6 +2,8 @@ source ./functions.sh +unset DOCKER_HOST + if [ "$1" == "" ]; then echo "Parameter 1 is empty" exit 1 @@ -28,7 +30,8 @@ exec_path="$(realpath "$exec_path")" results_path="$(realpath "$results_path")" pushd containers/compiler > /dev/null -compiler_image=$(docker build -q .) || exit 1 +compiler_image="ic$runner_id" +docker build -q -t $compiler_image . || exit 1 catch compiler_stdout compiler_stderr docker run \ --rm \ --network none \ @@ -47,12 +50,13 @@ printf '%s' "$compiler_stdout" > $results_path/c.0 printf '%s' "$compiler_stderr" > $results_path/c.1 if [ $compiler_status -eq 0 ]; then - runner_image=$(\ - docker build \ - --build-arg "EXEC_DIR_HOST=$exec_path_relative" \ - -q \ - -f "containers/runner/Dockerfile" . - ) || exit 1 + runner_image="ir$runner_id" + docker build \ + --build-arg "EXEC_DIR_HOST=$exec_path_relative" \ + -q \ + -t "$runner_image" \ + -f "containers/runner/Dockerfile" . \ + || exit 1 catch runner_stdout runner_stderr timeout 60 docker run \ --rm \ -h "java-runner-$runner_id" \ @@ -60,7 +64,7 @@ if [ $compiler_status -eq 0 ]; then --cpus=0.25 \ --network none \ -e "APPLICATION_NAME=$application_name" \ - $runner_image + "$runner_image" runner_status=$? docker image rm -f $runner_image > /dev/null || exit 1 @@ -68,7 +72,3 @@ if [ $compiler_status -eq 0 ]; then printf '%s' "$runner_stdout" > $results_path/r.0 printf '%s' "$runner_stderr" > $results_path/r.1 fi - -php generate-status-object.php $runner_id - -rm -rf "$runner_dir" diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..056bd4f --- /dev/null +++ b/compose.yml @@ -0,0 +1,7 @@ +services: + main: + build: . + privileged: true + ports: + - 13821:80 + environment: {} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..7914676 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cd /usr/local/bin/ +./dockerd-entrypoint.sh & +./httpd-foreground & +wait diff --git a/generate-status-object.php b/generate-status-object.php deleted file mode 100644 index 9d19070..0000000 --- a/generate-status-object.php +++ /dev/null @@ -1,30 +0,0 @@ - [ - "status" => get("c.s"), - "stdout" => get("c.0"), - "stderr" => get("c.1"), - ], - "run" => [ - "status" => get("r.s"), - "stdout" => get("r.0"), - "stderr" => get("r.1"), - ], -]; - -echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL; diff --git a/httpd-foreground b/httpd-foreground new file mode 100644 index 0000000..e896168 --- /dev/null +++ b/httpd-foreground @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +# Apache gets grumpy about PID files pre-existing +rm -f /usr/local/apache2/logs/httpd.pid + +exec httpd -DFOREGROUND "$@" diff --git a/httpd.conf b/httpd.conf new file mode 100644 index 0000000..0ddc08d --- /dev/null +++ b/httpd.conf @@ -0,0 +1,97 @@ +ServerTokens OS + +ServerRoot /var/www + +Listen 80 + +LoadModule mpm_prefork_module modules/mod_mpm_prefork.so +LoadModule authn_file_module modules/mod_authn_file.so +LoadModule authn_core_module modules/mod_authn_core.so +LoadModule authz_host_module modules/mod_authz_host.so +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so +LoadModule authz_user_module modules/mod_authz_user.so +LoadModule authz_core_module modules/mod_authz_core.so +LoadModule access_compat_module modules/mod_access_compat.so +LoadModule auth_basic_module modules/mod_auth_basic.so +LoadModule reqtimeout_module modules/mod_reqtimeout.so +LoadModule filter_module modules/mod_filter.so +LoadModule mime_module modules/mod_mime.so +LoadModule log_config_module modules/mod_log_config.so +LoadModule env_module modules/mod_env.so +LoadModule headers_module modules/mod_headers.so +LoadModule setenvif_module modules/mod_setenvif.so +LoadModule version_module modules/mod_version.so +LoadModule unixd_module modules/mod_unixd.so +LoadModule status_module modules/mod_status.so +LoadModule autoindex_module modules/mod_autoindex.so +LoadModule dir_module modules/mod_dir.so +LoadModule alias_module modules/mod_alias.so + +LoadModule negotiation_module modules/mod_negotiation.so + + +User apache2 +Group apache2 + + + +ServerAdmin you@example.com + +ServerSignature On + +ServerName localhost:80 + + + AllowOverride none + Require all denied + + +DocumentRoot "/opt/application/public" + + Options FollowSymLinks + + AllowOverride All + + Require all granted + + + + DirectoryIndex index.php index.html + + +# +# Require all denied +# + +#ErrorLog logs/error.log +ErrorLog /proc/self/fd/2 + +LogLevel warn + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + #CustomLog logs/access.log combined + CustomLog /proc/self/fd/1 combined + + + + RequestHeader unset Proxy early + + + + TypesConfig /etc/apache2/mime.types + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + + + MIMEMagicFile /etc/apache2/magic + + +IncludeOptional /etc/apache2/conf.d/*.conf diff --git a/public/index.php b/public/index.php index 0b3cabc..5a77566 100644 --- a/public/index.php +++ b/public/index.php @@ -3,6 +3,13 @@ session_name("a3e0f0ee-9f5a-4be2-88cb-3b7ceb626d00"); session_start(); +function get(string $id, string $name): ?string { + $file = __DIR__ . "/../_runners/$id/results/" . $name; + if (!is_file($file)) + return null; + return file_get_contents($file); +} + function csrf_token(): string { return $_SESSION["csrf-token"] = base64_encode(random_bytes(30)); } @@ -53,24 +60,62 @@ if (isset($_POST["code"]) && strlen($_POST["code"]) <= 16383) { exit; } - $srcDir = __DIR__ . "/../_runners/$id/src"; + $runnerDir = __DIR__ . "/../_runners/$id"; + $srcDir = $runnerDir . "/src"; mkdir($srcDir, recursive: true); file_put_contents($srcDir . "/Program.java", $code); + $isInDocker = getenv("IS_IN_DOCKER") === "1"; + + if ($isInDocker) + file_put_contents("php://stderr", "[debug] In Docker\n"); chdir(__DIR__ . "/.."); - $resultStr = shell_exec("./compile-and-run.sh '$id' Program 2>/dev/null"); + + $stderrFile = sys_get_temp_dir() . "/tmp{$id}.2"; + exec( + ($isInDocker ? "su-exec root " : "") . + "./compile-and-run.sh '$id' Program 2>'$stderrFile'", $resultStr, $code); + $resultStr = implode("\n", $resultStr); + if (is_file($stderrFile)) { + $stderrContents = file_get_contents($stderrFile); + unlink($stderrFile); + if (!empty($stderrContents)) { + file_put_contents("php://stderr", "compile-and-run.sh failed: $stderrContents\n"); + if ($code != 0) { + echo json_encode([ + "ok" => false, + "message" => "Execution failed:\n$stderrContents", + "csrf" => csrf_token(), + ]); + exit; + } + } + } chdir(__DIR__); + file_put_contents("php://stderr", "result: $result\n"); $csrf = csrf_token(); - if (is_string($resultStr)) { - $result = json_decode($resultStr, true); - $result["runner"] = $id; - $result["ok"] = true; - $result["csrf"] = $csrf; - } + + $result = [ + "compile" => [ + "status" => get($id, "c.s"), + "stdout" => get($id, "c.0"), + "stderr" => get($id, "c.1"), + ], + "run" => [ + "status" => get($id, "r.s"), + "stdout" => get($id, "r.0"), + "stderr" => get($id, "r.1"), + ], + "runner" => $id, + "ok" => true, + "csrf" => $csrf, + ]; + + delTree($runnerDir); echo json_encode($result); exit; -- cgit v1.2.3