docker push goes through the host daemon which can't resolve 'gitea' (not on any Docker network). crane pushes directly from the job container's network stack — resolves via Docker DNS, pushes over HTTP with --insecure. Flow: docker build → docker save → crane push - Build via host socket (works) - Save to tarball (local filesystem) - crane push tarball to gitea:3000 (job container DNS) Reverted DinD-rootless (needs privileged for user namespaces). Back to socket-mounted runner with daemonless push.