Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,31 @@ submits/
submit_results/
.venv/
node_modules/

# Python
__pycache__/
*.py[cod]
*.pyd
*.pyo
*.so
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
htmlcov/

# Node
**/dist/
**/.vite/

# VCS / tooling
.git/

# Local data (avoid baking into images)
kelvin_data/
**/*.log

# Editor
.vscode/
.idea/
.DS_Store
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
FROM ghcr.io/astral-sh/uv:python3.12-bookworm AS build-backend
FROM python:3.12-slim-bookworm AS build-backend

COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
-o APT::Install-Recommends=false \
-o APT::Install-Suggests=false \
build-essential \
libsasl2-dev \
libgraphviz-dev

Expand All @@ -26,7 +29,7 @@ RUN npm ci

RUN npm run build

FROM python:3.12-bookworm AS runtime
FROM python:3.12-slim-bookworm AS runtime

RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
Expand All @@ -43,6 +46,8 @@ WORKDIR /app
# We want to use ID 1000, to have the same ID as the default outside user
# And we also want group 101, to provide share access to the Unix uWSGI
# socket with the nginx image.
RUN groupadd -g 101 webserver

RUN useradd --uid 1000 --gid 101 --shell /bin/false --system webserver

RUN chown -R webserver .
Expand Down
6 changes: 5 additions & 1 deletion common/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ def evaluate_job(submit_url, task_url, token, meta):

logging.info(f"Evaluating {submit_url}")

with tempfile.TemporaryDirectory() as workdir:
# Create kelvin subdirectory in system temp (cross-platform)
kelvin_temp = os.path.join(tempfile.gettempdir(), "kelvin")
os.makedirs(kelvin_temp, exist_ok=True)

with tempfile.TemporaryDirectory(dir=kelvin_temp) as workdir:
os.chdir(workdir)

def untar(url, dest):
Expand Down
30 changes: 29 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,34 @@ services:
- app_static:/app/static:ro
- app_socket:/socket

evaluator:
container_name: kelvin_evaluator
profiles: [ evaluator ]
build:
context: evaluator
dockerfile: Dockerfile
image: "ghcr.io/mrlvsb/kelvin-evaluator:${EVALUATOR_IMAGE_TAG:-latest}"
pull_policy: always
restart: unless-stopped
group_add:
- "${DOCKER_GROUP_ID}"
environment:
# Option to specify Redis host and port to connect from other machines where evaluator runs,
# fallbacks to 'redis' hostname and default port, which means same machine
- REDIS__HOST=${REDIS__HOST:-redis}
- REDIS__PORT=${REDIS__PORT:-6379}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Mount /tmp/kelvin so Docker-in-Docker can access temporary evaluation directories
- /tmp/kelvin:/tmp/kelvin
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

deployment:
container_name: kelvin_deployment_service
profiles: [ prod ]
Expand All @@ -87,7 +115,7 @@ services:
pull_policy: always
restart: unless-stopped
group_add:
- "${DOCKER_GROUP_ID:?DOCKER_GROUP_ID is not set}"
- "${DOCKER_GROUP_ID}"
environment:
# Hardcode the docker-compose.yml path inside the container to match the repository volume mount path (must be in sync with volume that mounts the repo)
- DOCKER__COMPOSE_FILE_PATH=/kelvin/docker-compose.yml
Expand Down
33 changes: 33 additions & 0 deletions evaluator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM ghcr.io/mrlvsb/kelvin:latest

USER root

RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
-o APT::Install-Recommends=false \
-o APT::Install-Suggests=false \
ca-certificates \
curl

RUN curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
RUN chmod a+r /etc/apt/keyrings/docker.asc

RUN echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null

RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
-o APT::Install-Recommends=false \
-o APT::Install-Suggests=false \
docker-ce docker-ce-cli containerd.io docker-compose-plugin && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

USER webserver

ENTRYPOINT ["python", "manage.py", "rqworker"]
CMD ["default", "evaluator", "--with-scheduler"]
32 changes: 14 additions & 18 deletions evaluator/images/base/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
FROM ubuntu:24.04

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
-o APT::Install-Recommends=false \
-o APT::Install-Suggests=false \
locales=2.39-0ubuntu8 \
gcc=4:13.2.0-7ubuntu1 \
g++=4:13.2.0-7ubuntu1 \
gdb=15.0.50.20240403-0ubuntu1 \
nasm=2.16.01-1build1 \
python3=3.12.3-0ubuntu2.1 \
python3-pip=24.0+dfsg-1ubuntu1 \
python3-wheel=0.42.0-2 \
cmake=3.28.3-1build7 && \
rm -rf /var/lib/apt/lists/*

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
python3-pip && \
rm -rf /var/lib/apt/lists/*

# For HTML sanitization
RUN python3 -m pip install --break-system-packages bleach==5.0.1
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

# Workaround for https://github.com/dotnet/sdk/issues/31457
# It is included here, because it has to be present not only for building .NET projects,
# but also for running them (e.g. in the `run` image).
ENV DOTNET_EnableWriteXorExecute=0
RUN python3 -m pip install --break-system-packages bleach==6.3.0
4 changes: 2 additions & 2 deletions evaluator/images/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ def build_deps(arg):
return r


deps = {}
deps: dict[str, list[str]] = {}
base_path = os.path.dirname(os.path.realpath(__file__))
for path in Path(base_path).rglob("Dockerfile"):
name = "kelvin/" + os.path.basename(os.path.dirname(path))

parent = None
with open(path) as f:
with open(path, "r") as f:
for line in f:
parts = line.strip().split(" ")
if parts[0].upper() == "FROM":
Expand Down
15 changes: 8 additions & 7 deletions evaluator/images/cargo/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
FROM rust:1.90.0

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
-o APT::Install-Recommends=false \
-o APT::Install-Suggests=false \
python3-pip && \
rm -rf /var/lib/apt/lists/*
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# For HTML sanitization
RUN python3 -m pip install --break-system-packages bleach==5.0.1
RUN python3 -m pip install --break-system-packages bleach==6.3.0

RUN rustup component add clippy

ADD entry.py /
CMD /entry.py
Loading
Loading