From bc1f6a0ac36004fdc5def3ae358b9dff02dc8fb8 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sat, 2 May 2026 18:16:11 +0200 Subject: [PATCH] feat: add debian:13-slim runner image for Gitea Actions Self-contained Dockerfile under linux/debian/ that bakes runner user, Docker CE, Node.js v20+v24, latest Go, yq, and act env vars. Uses Debian's git-lfs and Docker CE from download.docker.com. Published to git.ipng.ch/ipng/gitea-debian-runner:13-slim. README documents build and push commands (single-arch and multi-arch via buildx). Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 41 ++++++++++ linux/debian/Dockerfile | 160 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 linux/debian/Dockerfile diff --git a/README.md b/README.md index 317c6d9..40ff87f 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,47 @@ - `ghcr.io/catthehacker/ubuntu:custom-24.04` - `ghcr.io/catthehacker/ubuntu:custom-latest` +## IPng Debian Runner + +A `debian:13-slim`-based variant of the `act`/`runner` image, intended for use with Gitea Actions. Compared to the Ubuntu images it adds `rsync`, ships `git-lfs` from Debian's archive (rather than the packagecloud repo), and uses Docker CE from `download.docker.com` instead of Microsoft's moby builds. + +Source: [`linux/debian/Dockerfile`](./linux/debian/Dockerfile). It is a single self-contained Dockerfile (no helper scripts) and bakes the `runner` user, Docker CE, Node.js LTS (v20 + v24), the latest stable Go release from go.dev, `yq`, and the `act`/runner environment variables (`ImageOS=debian13`, tool cache paths, etc.). + +Published to `git.ipng.ch/ipng/gitea-debian-runner:13-slim`. + +### Build + +```sh +docker build --load \ + --file linux/debian/Dockerfile \ + --tag git.ipng.ch/ipng/gitea-debian-runner:13-slim \ + --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + --build-arg BUILD_REF="$(git rev-parse HEAD)" \ + . +``` + +`--load` makes the image available to the local docker daemon — required when buildx uses the `docker-container` driver (the default on multi-platform setups). + +For multi-arch (amd64 + arm64) using buildx, building and pushing in one step: + +```sh +docker buildx build \ + --file linux/debian/Dockerfile \ + --platform linux/amd64,linux/arm64 \ + --tag git.ipng.ch/ipng/gitea-debian-runner:13-slim \ + --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + --build-arg BUILD_REF="$(git rev-parse HEAD)" \ + --push \ + . +``` + +### Push (single-arch) + +```sh +docker login git.ipng.ch +docker push git.ipng.ch/ipng/gitea-debian-runner:13-slim +``` + ## [`ubuntu-20.04` has been deprecated and images for that environment will not be updated anymore](https://github.com/actions/runner-images/pull/11748) ## [`ubuntu-18.04` has been deprecated and images for that environment will not be updated anymore](https://github.com/actions/runner-images/issues/6002) diff --git a/linux/debian/Dockerfile b/linux/debian/Dockerfile new file mode 100644 index 0000000..5844fdb --- /dev/null +++ b/linux/debian/Dockerfile @@ -0,0 +1,160 @@ +FROM debian:13-slim + +ARG TARGETARCH +ARG NODE_VERSION="20 24" +ARG RUNNER=runner +ARG BUILD_DATE +ARG BUILD_REF +ARG BUILD_TAG=gitea-debian-runner +ARG BUILD_TAG_VERSION=13-slim +ARG BUILD_OWNER=ipng +ARG BUILD_REPO=gitea-debian-runner + +ENV DEBIAN_FRONTEND=noninteractive \ + ImageOS=debian13 \ + IMAGE_OS=debian13 \ + LSB_RELEASE=13 \ + LSB_OS_VERSION=13 \ + AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache \ + RUN_TOOL_CACHE=/opt/hostedtoolcache \ + ACT_TOOLSDIRECTORY=/opt/acttoolcache \ + DEPLOYMENT_BASEPATH=/opt/runner \ + RUNNER_TEMP=/home/runner/work/_temp \ + USER=runner \ + RUNNER_USER=runner \ + PATH=/home/runner/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +SHELL ["/bin/bash", "--login", "-eo", "pipefail", "-c"] +WORKDIR /tmp + +RUN <<'EOF' +set -Eeuxo pipefail + +node_arch() { + case "$(uname -m)" in + aarch64) echo arm64 ;; + x86_64) echo x64 ;; + armv7l) echo armv7l ;; + *) exit 1 ;; + esac +} +yq_arch() { + case "$(uname -m)" in + aarch64) echo arm64 ;; + x86_64) echo amd64 ;; + armv7l) echo arm ;; + *) exit 1 ;; + esac +} +go_arch() { + case "$(uname -m)" in + aarch64) echo arm64 ;; + x86_64) echo amd64 ;; + armv7l) echo armv6l ;; + *) exit 1 ;; + esac +} + +apt-get -yq update +apt-get -yq install --no-install-recommends \ + ca-certificates curl wget gnupg ssh sudo gawk jq \ + zstd zip unzip xz-utils \ + git git-lfs rsync \ + python3-pip python3-venv pipx \ + libyaml-0-2 + +ln -sf "$(command -v python3)" /usr/local/bin/python +git config --system --add safe.directory '*' + +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc +chmod a+r /etc/apt/keyrings/docker.asc +. /etc/os-release +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian ${VERSION_CODENAME} stable" \ + > /etc/apt/sources.list.d/docker.list +apt-get -yq update +apt-get -yq install --no-install-recommends \ + docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +mkdir -m 0700 -p /root/.ssh +{ ssh-keyscan github.com; ssh-keyscan ssh.dev.azure.com; } >> /etc/ssh/ssh_known_hosts + +sed -i 's|"||g' /etc/environment +{ + echo "ImageOS=${ImageOS}" + echo "IMAGE_OS=${IMAGE_OS}" + echo "LSB_RELEASE=${LSB_RELEASE}" + echo "LSB_OS_VERSION=${LSB_OS_VERSION}" + echo "AGENT_TOOLSDIRECTORY=${AGENT_TOOLSDIRECTORY}" + echo "RUN_TOOL_CACHE=${RUN_TOOL_CACHE}" + echo "ACT_TOOLSDIRECTORY=${ACT_TOOLSDIRECTORY}" + echo "DEPLOYMENT_BASEPATH=${DEPLOYMENT_BASEPATH}" + echo "USER=${USER}" + echo "RUNNER_USER=${RUNNER_USER}" + echo "RUNNER_TEMP=${RUNNER_TEMP}" +} >> /etc/environment + +mkdir -m 0777 -p "${AGENT_TOOLSDIRECTORY}" "${ACT_TOOLSDIRECTORY}" /github + +IFS=' ' read -r -a NODE <<<"${NODE_VERSION}" +for ver in "${NODE[@]}"; do + if [[ "${ver}" == "24" && "$(node_arch)" == "armv7l" ]]; then + ver=22 + fi + VER=$(curl -fsSL https://nodejs.org/download/release/index.json \ + | jq -r "[.[] | select(.version|test(\"^v${ver}\\\\.\"))][0].version") + NODEPATH="${ACT_TOOLSDIRECTORY}/node/${VER:1}/$(node_arch)" + mkdir -m 0777 -p "${NODEPATH}" + wget -q "https://nodejs.org/download/release/latest-v${ver}.x/node-${VER}-linux-$(node_arch).tar.xz" -O node.tar.xz + tar -Jxf node.tar.xz --strip-components=1 -C "${NODEPATH}" + rm node.tar.xz + if [[ "${ver}" == "24" || ( "${ver}" == "22" && "$(node_arch)" == "armv7l" ) ]]; then + ln -sfn "${NODEPATH}" "${ACT_TOOLSDIRECTORY}/node/current" + ln -sf "${NODEPATH}"/bin/node "${NODEPATH}"/bin/npm "${NODEPATH}"/bin/npx "${NODEPATH}"/bin/corepack /usr/local/bin/ + fi +done + +base_url=https://github.com/mikefarah/yq/releases/latest/download +wget -q "${base_url}/yq_linux_$(yq_arch)" -O /usr/bin/yq +chmod +x /usr/bin/yq + +GO_VER=$(curl -fsSL 'https://go.dev/dl/?mode=json' | jq -r '.[0].version' | sed 's/^go//') +GO_PATH="${ACT_TOOLSDIRECTORY}/go/${GO_VER}/$(go_arch)" +mkdir -m 0777 -p "${GO_PATH}" +wget -qO- "https://go.dev/dl/go${GO_VER}.linux-$(go_arch).tar.gz" | tar -zxf - --strip-components=1 -C "${GO_PATH}" +touch "${GO_PATH}.complete" +ln -sf "${GO_PATH}"/bin/* /usr/local/bin/ + +groupadd -g 1001 "${RUNNER}" +RUNNERADMIN="${RUNNER}admin" +groupadd -g 1000 "${RUNNERADMIN}" || RUNNERADMIN="$(id -gn 1000)" +useradd -u 1001 -g "${RUNNER}" -G sudo -m -s /bin/bash "${RUNNER}" +useradd -u 1000 -g "${RUNNERADMIN}" -G sudo -m -s /bin/bash "${RUNNERADMIN}" || true +usermod -aG docker "${RUNNER}" +usermod -aG docker "${RUNNERADMIN}" +{ + echo "${RUNNER} ALL=(ALL) NOPASSWD: ALL" + echo "${RUNNERADMIN} ALL=(ALL) NOPASSWD: ALL" +} >> /etc/sudoers + +mkdir -p "/home/${RUNNER}/work/_temp" +mkdir -m 0700 -p "/home/${RUNNER}/.ssh" +{ ssh-keyscan -t rsa github.com; ssh-keyscan -t rsa ssh.dev.azure.com; } > "/home/${RUNNER}/.ssh/known_hosts" +chmod 644 "/home/${RUNNER}/.ssh/known_hosts" +chown -R "${RUNNER}":"${RUNNER}" "/home/${RUNNER}" +chown -R "${RUNNER}":"${RUNNERADMIN}" "${AGENT_TOOLSDIRECTORY}" "${ACT_TOOLSDIRECTORY}" /github + +apt-get clean +rm -rf /var/cache/* /var/log/* /var/lib/apt/lists/* /tmp/* || true +EOF + +LABEL org.opencontainers.image.created="${BUILD_DATE}" +LABEL org.opencontainers.image.vendor="${BUILD_OWNER}" +LABEL org.opencontainers.image.url="https://git.ipng.ch/${BUILD_OWNER}/${BUILD_REPO}" +LABEL org.opencontainers.image.source="https://git.ipng.ch/${BUILD_OWNER}/${BUILD_REPO}" +LABEL org.opencontainers.image.version="${BUILD_TAG_VERSION}" +LABEL org.opencontainers.image.title="${BUILD_TAG}-${TARGETARCH}" +LABEL org.opencontainers.image.description="IPng Debian Runner — Gitea Actions runner image based on debian:13-slim, with git-lfs, rsync and Go" +LABEL org.opencontainers.image.revision="${BUILD_REF}" + +USER ${RUNNER}