From e27f1534795a2fd5d605fcde7d9f18d271552af6 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Wed, 2 Sep 2026 16:30:04 +0530 Subject: [PATCH] Wait for docker daemon before build (fix container-start race) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build #7 failed with "Cannot connect to the Docker daemon at tcp://localhost:2375" right at the first sh step. Verified the dind entrypoint script directly (docker-library/docker's dockerd-entrypoint.sh) — with DOCKER_TLS_CERTDIR="" and a dash-prefixed arg it correctly builds `dockerd --host=tcp://0.0.0.0:2375 --insecure-registry=...`, so the --insecure-registry flag added last commit isn't logically wrong. This is a container-start race instead: Kubernetes doesn't guarantee ordering between containers in the same pod, so the docker-cli container's first sh can fire before dockerd in the sibling container has finished its startup checks (iptables detection etc. run on every start). Polls `docker info` for up to 60s before the actual build instead of assuming instant availability. --- src/com/homelab/stages/buildDocker.groovy | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/com/homelab/stages/buildDocker.groovy b/src/com/homelab/stages/buildDocker.groovy index e736c35..31902a3 100644 --- a/src/com/homelab/stages/buildDocker.groovy +++ b/src/com/homelab/stages/buildDocker.groovy @@ -24,6 +24,7 @@ def run(Map config) { try { stage(stageName('Build & push image')) { container('docker-cli') { + waitForDockerDaemon() dir("${config.repo_name}") { if (!fileExists('Dockerfile')) { renderDockerfile(config) @@ -43,6 +44,25 @@ def run(Map config) { return tag } +// Kubernetes doesn't guarantee container-start ordering within a pod, so +// the sibling `docker` (dind) container can still be initializing +// (iptables detection, cert-dir checks, etc. run on every start) when +// this container's very first `sh` step fires — hit exactly this as +// "Cannot connect to the Docker daemon at tcp://localhost:2375" on a +// build that had worked fine moments earlier. Poll rather than assume +// instant availability. +def waitForDockerDaemon() { + sh ''' + for i in $(seq 1 30); do + docker info >/dev/null 2>&1 && exit 0 + echo "Waiting for docker daemon to be ready... ($i/30)" + sleep 2 + done + echo "docker daemon never became ready" >&2 + exit 1 + ''' +} + // Only reached when the repo has no Dockerfile of its own. Requires // config.dockerBuildVersion (e.g. 'go-1.22') — there's no sensible // default to fall back to if a repo has neither a Dockerfile nor this