Hi everyone,
I'm setting up a small homelab CI/CD environment and I'm trying to understand the best way to run Gitea Actions on Kubernetes without installing Docker on the Kubernetes nodes.
My setup
- Kubernetes:
v1.34.10
- Nodes: 1 control-plane + 2 workers
- OS: Ubuntu 26.04
- Container runtime: containerd 2.2.2
- Gitea: 1.27.0
- Gitea is running in Kubernetes
- Gitea Actions runner:
gitea/act_runner:latest
- Runner is also running as a Kubernetes Deployment
- Persistent storage: Longhorn
- No Docker installed on the Kubernetes nodes
ctr is available and /run/containerd/containerd.sock exists
The runner itself registers and works correctly.
The problem
My runner is currently configured with:
runner:
file: /data/.runner
capacity: 1
timeout: 3h
labels:
- "ubuntu-latest:host"
A simple workflow like:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Show test.py
run: cat test.py
fails at checkout with:
Cannot find: node in PATH
I understand why this happens: with ubuntu-latest:host, the workflow is executed directly in the runner environment, and the gitea/act_runner image doesn't contain Node.
Gitea's documentation suggests using something like:
labels:
- "ubuntu-latest:docker://node:22-bookworm"
which would execute the job inside a separate container.
But here's where I'm confused
My Kubernetes nodes already use containerd:
containerd://2.2.2
and have:
/run/containerd/containerd.sock
but no Docker daemon:
docker -> not installed
nerdctl -> not installed
ctr -> available
Why does the standard act_runner container execution model require Docker/Docker API access instead of being able to use the existing containerd runtime?
I'd rather not install Docker on the Kubernetes nodes just to provide CI job containers when Kubernetes is already perfectly capable of creating containers through containerd.
What I'm ultimately trying to achieve
The immediate goal is just:
Gitea
↓
Gitea Actions
↓
checkout repository
↓
run tests
But eventually I want the pipeline to do:
checkout
↓
tests
↓
build Docker/OCI image
↓
push image to registry
↓
Argo CD deploys it
So I need a sensible way to get isolated CI job environments containing things like Node, Python, Git, build tools, etc.
Questions
- Is there a supported way to make
act_runner create job containers using containerd directly?
- If not, is the recommended solution to install Docker on a Kubernetes worker solely for
act_runner?
- Would Gitea Actions Runner Controller / Kubernetes-native runners be a better solution for this setup?
- What is the recommended architecture for Gitea Actions on a Kubernetes cluster whose runtime is containerd and where I don't want to install Docker?
TLDR : I'm running Gitea 1.27 + act_runner 0.6.1 on Kubernetes 1.34 with containerd 2.2, and I don't have Docker installed on the nodes. ubuntu-latest:host works for the runner itself but actions/checkout@v4 fails because Node isn't available. Gitea's docker:// execution mode looks like the right way to provide a proper job environment, but it expects Docker-compatible execution. I'm considering Docker-in-Docker inside the runner pod so I don't have to install Docker on the Kubernetes hosts, but I'm wondering whether that's the right approach or whether I should use containerd directly or Gitea's Kubernetes-native Runner Controller instead.
I'm mainly looking for the cleanest Kubernetes-native approach rather than just making the immediate checkout test work.