The 2026-09-05 rewrite dropped the dns: list, so dockerd inside dind
inherited the host's systemd-resolved (Tailscale DNS enabled) through
Docker's embedded resolver and got SERVFAIL for every public name -- every
job then died pulling the runner image, and Gitea left the jobs orphaned.
Restores three settings, each documented inline: dns: for dockerd's own
pulls, --dns for the job containers (tailnet resolver first, public second,
so MagicDNS names resolve inside a job), and --default-address-pool so a CI
run cannot exhaust the fifteen default /16s.
Committed this time. The same settings were applied on 2026-09-03 without a
commit and were lost to the next rewrite.
1) Cache act_runner phải nằm trên volume.
Mặc định cache.dir rỗng -> act_runner ghi vào $HOME/.cache/actcache, tức
WRITABLE LAYER của container. Đo thực tế trên ba máy: 278 GB / 95 GB / 32 GB
nằm ở đó, mất sạch chỉ với một lệnh docker compose up -d.
Thêm volume runner-cache mount vào /cache và đặt cache.dir="/cache".
Hai chỗ này phải luôn đổi cùng nhau.
2) Ghim image theo digest thay vì :nightly.
Tag tự cập nhật nghĩa là compose pull có thể tạo lại container sau lưng, kéo
theo mất cache. Nâng cấp có chủ đích: đổi digest, commit, rồi mới áp dụng.
3) XOÁ runner.sh.
Nó lỗi thời (đã thay bằng docker compose) và quan trọng hơn: nó chứa
GITEA_RUNNER_REGISTRATION_TOKEN dạng plaintext đã commit vào git. Ai có token
đó đăng ký được runner vào Gitea, tức chạy job tuỳ ý trên hạ tầng này.
XOÁ FILE LÀ CHƯA ĐỦ - token vẫn nằm trong lịch sử git, BẮT BUỘC phải thu hồi
và cấp lại token trong Gitea.
4) README: bổ sung bước clone cho máy builder mới, cảnh báo phải kiểm tra job
đang chạy trước khi tạo lại runner (tạo lại là mồ côi job đang chạy), và
phần dọn rác trong DinD (image/volume/build cache không tự dọn - một máy đo
được 515 image thừa và 71 GB build cache).
The previous fix (docker_host: tcp://dind:2375) was wrong: act_runner
never passes DOCKER_HOST into job containers as an env var. It always
bind-mounts container.docker_host (read from ITS OWN filesystem) into
every job container as /var/run/docker.sock, and only recognizes
unix:// (or bare) paths -- a tcp:// value is silently treated as
unknown and falls back to a /var/run/docker.sock that doesn't exist in
the runner container, which is exactly the "no such file or directory"
error.
Expose dind's daemon over an additional unix socket on a volume shared
with the runner (dind-sock), and point docker_host at that shared path
so the bind-mount act_runner performs actually resolves to dind's real
socket. Verified by replicating act_runner's exact bind-mount pattern
against the running stack: `docker -H tcp://dind:2375 run -v
/dind-sock/docker.sock:/var/run/docker.sock ...` successfully ran
`docker info` and `docker build` inside a nested container.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFsukF6FzwBxJtRGzbt28F
docker_host: "-" was disabling docker access in job containers entirely,
so steps running `docker build`/`docker` directly had no daemon to talk
to. Point docker_host at the dind sibling and add a host-gateway entry
so the "dind" hostname resolves inside job containers, which run nested
on dind's own internal bridge network rather than the outer compose one.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFsukF6FzwBxJtRGzbt28F
Stable docker-compose setup for building Rust projects on Gitea Actions.
DinD-isolated daemon, built-in cache server, capacity=4 parallel jobs,
healthcheck-gated startup. Portable to other build machines via .env.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HU4wDwdydNZpR3YkMiYYy8