Files

138 lines
6.4 KiB
Markdown
Raw Permalink Normal View History

2026-08-27 10:46:36 +02:00
# Build Docker images on k3s with Gitea Actions → push to Harbor
This repository contains a complete, reproducible configuration that lets you:
1. Run a **Gitea Actions runner** (`act_runner`) **on a k3s node**.
2. Build **Docker/OCI container images** inside the CI pipeline using a
**Docker-in-Docker (DinD)** sidecar (so plain `docker build` / `docker push` work).
3. **Push the built images to a Harbor** registry.
The whole pipeline is driven by **Gitea Actions** (Gitea's built-in, GitHub-Actions-compatible
CI/CD), so no external CI system (Jenkins/Drone/etc.) is required.
```
┌──────────────┐ registers ┌─────────────────────────────────────┐
│ Gitea │◄────────────────│ act_runner (Deployment on k3s) │
│ (Actions) │ job dispatch │ ┌───────────────┐ ┌──────────────┐ │
│ │────────────────►│ │ act_runner │ │ dockerd │ │
└──────────────┘ │ │ container │─►│ (DinD side- │ │
▲ │ └───────────────┘ │ car, │ │
│ git push │ docker build │ privileged)│ │
┌────┴─────┐ │ docker push └──────────────┘ │
│ developer│ └───────────────────────────┬─────────┘
└──────────┘ │ push image
▼
┌──────────────────┐
│ Harbor registry │
└──────────────────┘
```
---
## Repository layout
| File | Purpose |
|------|---------|
| [k3s/00-namespace.yaml](k3s/00-namespace.yaml) | Dedicated `gitea-runner` namespace. |
| [k3s/10-runner-secret.yaml.example](k3s/10-runner-secret.yaml.example) | Gitea registration token secret (copy & fill in). |
| [k3s/20-runner-config.yaml](k3s/20-runner-config.yaml) | `act_runner` config (`config.yaml`) as a ConfigMap. |
| [k3s/30-runner-deployment.yaml](k3s/30-runner-deployment.yaml) | The `act_runner` + DinD Deployment. |
| [k3s/40-harbor-secret.yaml.example](k3s/40-harbor-secret.yaml.example) | Optional cluster-side Harbor pull secret. |
| [workflows/build-and-push.yaml](workflows/build-and-push.yaml) | Example Gitea Actions workflow (put in your app repo). |
| [examples/Dockerfile](examples/Dockerfile) | Minimal sample image to build. |
| [scripts/deploy.sh](scripts/deploy.sh) | Helper to apply all manifests. |
| [.gitea/workflows/build-and-push.yaml](.gitea/workflows/build-and-push.yaml) | Same workflow, pre-placed so *this* repo self-builds. |
---
## Prerequisites
* A running **k3s** cluster and `kubectl` access to it (`~/.kube/config` or `/etc/rancher/k3s/k3s.yaml`).
* A reachable **Gitea** instance (>= 1.20) with **Actions enabled**
(`[actions] ENABLED = true` in Gitea's `app.ini`).
* A running **Harbor** registry and a **robot account** (recommended) with `push` permission
on the target project.
---
## Step 1 — Enable Gitea Actions (on the Gitea server)
In Gitea's `app.ini`:
```ini
[actions]
ENABLED = true
```
Restart Gitea. Then get a **runner registration token**:
* **Instance level:** *Site Administration → Actions → Runners → Create new Runner* → copy the token.
* **Org/Repo level:** *Settings → Actions → Runners → Create new Runner*.
---
## Step 2 — Create the runner registration secret
```bash
cp k3s/10-runner-secret.yaml.example k3s/10-runner-secret.yaml
# edit k3s/10-runner-secret.yaml and paste your GITEA_INSTANCE_URL + token
kubectl apply -f k3s/10-runner-secret.yaml
```
## Step 3 — Deploy the runner on k3s
```bash
./scripts/deploy.sh
# or manually:
kubectl apply -f k3s/00-namespace.yaml
kubectl apply -f k3s/20-runner-config.yaml
kubectl apply -f k3s/30-runner-deployment.yaml
```
Verify the runner appears **online** in Gitea (*Actions → Runners*) and that both containers are ready:
```bash
kubectl -n gitea-runner rollout status deploy/act-runner
kubectl -n gitea-runner get pods
```
## Step 4 — Configure Harbor credentials for the pipeline
In your **Gitea repository** (or org) → *Settings → Actions → Secrets*, add:
| Secret name | Value |
|-------------|-------|
| `HARBOR_REGISTRY` | e.g. `harbor.example.com` |
| `HARBOR_USERNAME` | Harbor user / robot account, e.g. `robot$ci` |
| `HARBOR_PASSWORD` | the robot account token / password |
> Using a **Harbor robot account** (Project → Robot Accounts) instead of a personal
> login is strongly recommended.
## Step 5 — Add the workflow to your app repo
Copy [workflows/build-and-push.yaml](workflows/build-and-push.yaml) into your application repository at
`.gitea/workflows/build-and-push.yaml`, commit, and push. Gitea will dispatch the job to your
k3s runner, which builds the image via DinD and pushes it to Harbor.
---
## How image building works (no Docker on k3s needed)
k3s uses **containerd**, not Docker, and has no image-build capability. This setup therefore runs a
**dockerd DinD sidecar** next to `act_runner`. The runner container talks to it over
`tcp://localhost:2376` (TLS), so inside jobs the standard `docker` CLI works transparently —
`docker build`, `docker login`, `docker push` all behave like on a normal Docker host.
If you prefer a **rootless / non-privileged** approach (Kaniko or Buildah), see the
"Alternative: rootless builds" section at the bottom of
[workflows/build-and-push.yaml](workflows/build-and-push.yaml).
## Security notes
* The DinD sidecar requires `privileged: true`. Keep this runner in its own namespace and,
ideally, on a dedicated node (see the `nodeSelector`/`tolerations` comments in the Deployment).
* Prefer Harbor **robot accounts** with the least privilege (push to one project only).
* Store all credentials as Kubernetes/Gitea secrets — never commit the filled-in
`*.yaml` (non-`.example`) files. See [.gitignore](.gitignore).