Billionmail/BillionMail · error

Failed to connect to Docker API: %v

Error message

Failed to connect to Docker API: %v

What it means

getDKIMRecordWithKeySize needs a Docker client (docker.NewDockerAPI) to exec rspamadm key generation inside the Rspamd container. This error wraps client-construction failure — typically the Docker socket is unreachable or DOCKER_HOST is misconfigured. No DKIM record can be generated or read without it.

Source

Thrown at core/internal/service/domains/domains.go:543

func getDKIMRecordWithKeySize(domain, selector string, keySize int, validateImmediate bool) (record v1.DNSRecord, err error) {
	// Create DKIM directory
	dkimPath := public.AbsPath(filepath.Join(consts.RSPAMD_LIB_PATH, "dkim", domain))

	// Check if directory exists
	if !public.IsDir(dkimPath) {
		_ = os.MkdirAll(dkimPath, 0755)
	}

	// Check if DKIM private and public key files exist
	dkimPriPath := filepath.Join(dkimPath, selector+".private")
	dkimPubPath := filepath.Join(dkimPath, selector+".pub")

	var dk *docker.DockerAPI

	dk, err = docker.NewDockerAPI()
	if err != nil {
		err = fmt.Errorf("Failed to connect to Docker API: %v", err)
		return
	}
	defer dk.Close()

	// Generate new keys if they don't exist
	if !public.FileExists(dkimPriPath) || !public.FileExists(dkimPubPath) {
		mutex.Lock()
		defer mutex.Unlock()

		var res *v2.ExecResult
		res, err = dk.ExecCommandByName(context.Background(), consts.SERVICES.Rspamd, []string{"rspamadm", "dkim_keygen", "-s", selector, "-b", fmt.Sprintf("%d", keySize), "-d", domain, "-k", fmt.Sprintf("/var/lib/rspamd/dkim/%s/%s.private", domain, selector)}, "root")
		if err != nil {
			err = fmt.Errorf("Failed to generate DKIM key pair: %v", err)
			return
		}

		if res != nil {
			_, err = public.WriteFile(dkimPubPath, res.Output)

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify Docker is running: systemctl status docker / docker info
  2. Check the Docker socket is mounted and writable in the app container (e.g. /var/run/docker.sock volume + group permissions)
  3. Check DOCKER_HOST env is correct if using a remote daemon
  4. Run the app inside the deployment environment where Docker access is provisioned

Example fix

// before
dk, err = docker.NewDockerAPI()
if err != nil { err = fmt.Errorf("Failed to connect to Docker API: %v", err); return }
// after
dk, err = docker.NewDockerAPI()
if err != nil {
    err = fmt.Errorf("Failed to connect to Docker API (check /var/run/docker.sock and DOCKER_HOST): %v", err)
    return
}
// precheck before calling
di, derr := docker.NewDockerAPI(); if derr != nil { return fmt.Errorf("docker unavailable: %w", derr) }
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat("/var/run/docker.sock"); err != nil {
    return fmt.Errorf("docker socket not mounted: %v", err)
}
if os.Getenv("DOCKER_HOST") != "" {
    return fmt.Errorf("DOCKER_HOST set to %s — verify daemon reachability", os.Getenv("DOCKER_HOST"))
}

Try / catch

dk, err := docker.NewDockerAPI()
if err != nil {
    return fmt.Errorf("Failed to connect to Docker API: %v", err) // bubble up; retry later once daemon recovers
}
defer dk.Close()

Prevention

When it happens

Trigger: GetDKIMRecord, GetDKIMShortRecord, or RepairDKIMSigningConfig when docker.NewDockerAPI() fails: /var/run/docker.sock missing or permission-denied, Docker daemon stopped, or DOCKER_HOST pointing to an unreachable endpoint (common when running the app outside the deployment container).

Common situations: App container not mounted with the Docker socket; user not in the docker group (permission denied on socket); DOCKER_HOST=tcp://... to a dead daemon; running the binary on a host without Docker during development.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/47f895ee291e528f. Report an issue: GitHub.