| 1 | # Diffinery runner image (Cloudflare Containers, linux/amd64). |
| 2 | # Build context: containers/runner. Run `pnpm build` first so dist/agent.mjs exists. |
| 3 | # |
| 4 | # docker build --platform linux/amd64 -t diffinery-runner containers/runner |
| 5 | ARG BASE_IMAGE=ubuntu:24.04 |
| 6 | FROM ${BASE_IMAGE} |
| 7 | |
| 8 | ARG NODE_VERSION=22.22.0 |
| 9 | |
| 10 | ENV DEBIAN_FRONTEND=noninteractive \ |
| 11 | LANG=C.UTF-8 \ |
| 12 | LC_ALL=C.UTF-8 \ |
| 13 | DIFFINERY_WORK_ROOT=/workspace \ |
| 14 | RUNNER_TOOL_CACHE=/opt/hostedtoolcache \ |
| 15 | AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache \ |
| 16 | COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ |
| 17 | # What hosted ubuntu-24.04 runners report; setup-* actions key their caches on it. |
| 18 | ImageOS=ubuntu24 \ |
| 19 | ImageVersion=20250101.1 \ |
| 20 | # Ubuntu 24.04 marks the system Python as externally managed (PEP 668); |
| 21 | # CI scripts commonly `pip install` directly, so allow it like hosted runners do. |
| 22 | PIP_BREAK_SYSTEM_PACKAGES=1 |
| 23 | |
| 24 | RUN apt-get update \ |
| 25 | && apt-get install -y --no-install-recommends \ |
| 26 | ca-certificates curl git git-lfs jq zip unzip xz-utils tar gzip zstd \ |
| 27 | build-essential pkg-config openssh-client gnupg \ |
| 28 | python3 python3-pip python3-venv python-is-python3 \ |
| 29 | && git config --system --add safe.directory '*' \ |
| 30 | && git lfs install --system --skip-repo \ |
| 31 | && apt-get clean \ |
| 32 | && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* |
| 33 | |
| 34 | # Node.js LTS from the official tarball (checksum-verified), with corepack shims for pnpm/yarn. |
| 35 | RUN set -eux; \ |
| 36 | cd /tmp; \ |
| 37 | file="node-v${NODE_VERSION}-linux-x64.tar.xz"; \ |
| 38 | curl -fsSLO "https://nodejs.org/dist/v${NODE_VERSION}/${file}"; \ |
| 39 | curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt" | grep " ${file}\$" | sha256sum -c -; \ |
| 40 | tar -xJf "${file}" -C /usr/local --strip-components=1 --no-same-owner \ |
| 41 | --exclude='*/CHANGELOG.md' --exclude='*/README.md' --exclude='*/LICENSE' --exclude='*/include/*' --exclude='*/share/doc/*'; \ |
| 42 | rm -f "${file}"; \ |
| 43 | corepack enable; \ |
| 44 | corepack prepare pnpm@10.28.0 --activate; \ |
| 45 | corepack prepare yarn@1.22.22 --activate; \ |
| 46 | node --version; npm --version; pnpm --version; yarn --version; \ |
| 47 | npm cache clean --force; \ |
| 48 | rm -rf /root/.npm /tmp/* |
| 49 | |
| 50 | # GitHub CLI (preinstalled on hosted runners; workflows call `gh` with GH_TOKEN). |
| 51 | RUN set -eux; \ |
| 52 | install -m 0755 -d /etc/apt/keyrings; \ |
| 53 | curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /etc/apt/keyrings/githubcli-archive-keyring.gpg; \ |
| 54 | echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list; \ |
| 55 | apt-get update; \ |
| 56 | apt-get install -y --no-install-recommends gh; \ |
| 57 | apt-get clean; \ |
| 58 | rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* |
| 59 | |
| 60 | # Docker Engine, started on first use by the /usr/local/bin/docker wrapper. Cloudflare |
| 61 | # Containers run it rootful with iptables, so bridge networks, service DNS, port |
| 62 | # publishing and builds all work like on GitHub's hosted runners. |
| 63 | RUN set -eux; \ |
| 64 | install -m 0755 -d /etc/apt/keyrings; \ |
| 65 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc; \ |
| 66 | echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list; \ |
| 67 | apt-get update; \ |
| 68 | apt-get install -y --no-install-recommends docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin iptables; \ |
| 69 | apt-get clean; \ |
| 70 | rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* |
| 71 | COPY image/daemon.json /etc/docker/daemon.json |
| 72 | COPY image/docker /usr/local/bin/docker |
| 73 | |
| 74 | RUN mkdir -p /workspace /opt/hostedtoolcache /opt/diffinery |
| 75 | COPY dist/agent.mjs /opt/diffinery/agent.mjs |
| 76 | |
| 77 | WORKDIR /workspace |
| 78 | EXPOSE 8080 |
| 79 | ENTRYPOINT ["node", "/opt/diffinery/agent.mjs"] |