{"record":{"id":"88c11bd872e25e7c","repo":"Billionmail/BillionMail","slug":"failed-to-pull-image-w","errorCode":null,"errorMessage":"failed to pull image: %w","messagePattern":"failed to pull image: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/dockerapi/dockerapi.go","lineNumber":280,"sourceCode":"\tresult := &HostCommandResult{\n\t\tExitCode: -1,\n\t}\n\n\t// Check if docker.sock is mounted\n\tif _, err := os.Stat(\"/var/run/docker.sock\"); os.IsNotExist(err) {\n\t\treturn nil, fmt.Errorf(\"docker.sock not mounted, cannot access Docker API\")\n\t}\n\n\t// Specify the base image to use\n\tbaseImage := \"alpine:latest\"\n\n\t// Check if the image exists, pull it if it doesn't\n\t_, err := d.client.ImageInspect(ctx, baseImage)\n\tif err != nil {\n\t\t// Image doesn't exist, try to pull it\n\t\treader, err := d.client.ImagePull(ctx, baseImage, image.PullOptions{})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to pull image: %w\", err)\n\t\t}\n\t\tdefer reader.Close()\n\n\t\t// Wait for the image pull to complete\n\t\t_, _ = io.Copy(io.Discard, reader)\n\t}\n\n\t// Create temporary container configuration\n\tconfig := &container.Config{\n\t\tImage:      baseImage,\n\t\tCmd:        command,\n\t\tWorkingDir: \"/host_root\", // Set working directory to mount point\n\t\tTty:        false,\n\t\tEntrypoint: []string{},\n\t}\n\n\t// Use privileged mode and mount the host's root directory\n\thostConfig := &container.HostConfig{","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/dockerapi/dockerapi.go#L262-L298","documentation":"ExecHostCommand needs an alpine image to launch its host-command container. It first inspects the image locally; if absent it calls ImagePull. Any failure pulling from the registry (auth, network, tag missing) aborts the host command with this wrapped error.","triggerScenarios":"alpine:latest not present locally AND ImagePull fails — no internet/DNS, registry rate-limited (Docker Hub 429), private mirror requires credentials, or image name/tag unavailable.","commonSituations":"Air-gapped or restricted-network deployments; Docker Hub pull throttling after repeated anonymous pulls; registry outage; IPv6/DNS problems in the container runtime.","solutions":["Pre-pull the image once: `docker pull alpine:latest` so ImageInspect succeeds and the pull path is skipped","Restore network/DNS from the host to the registry, or configure a reachable registry mirror in daemon.json","docker login to the required registry if pulls are authenticated/rate-limited","Pin a cached specific tag (e.g. alpine:3.20) instead of latest to reduce pull dependency"],"exampleFix":"// before\n# runtime pulls on demand, fails offline\n// after (deploy step)\ndocker pull alpine:latest && ./app  # image cached locally","handlingStrategy":"fallback","validationCode":"if _, err := d.client.ImageInspect(ctx, \"alpine:latest\"); err != nil {\n    if err := prePull(ctx, d.client, \"alpine:latest\"); err != nil {\n        return fmt.Errorf(\"image unavailable offline: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"res, err := api.ExecHostCommand(ctx, cmd)\nif err != nil && strings.Contains(err.Error(), \"failed to pull image\") {\n    log.Warnf(\"registry pull failed: %v — retrying or using cached tag\", err)\n    return runWithFallbackImage(ctx, \"alpine:3.20\", cmd)\n}","preventionTips":["Pre-pull alpine in the image build or entrypoint","Pin a specific alpine tag instead of latest","Configure a registry mirror for offline/restricted networks","docker login where pulls are rate-limited or authenticated"],"tags":["docker","network","image-pull"],"backgroundTag":"image-pull-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}