{"record":{"id":"f7e6c492d74758c6","repo":"Billionmail/BillionMail","slug":"docker-sock-not-mounted-cannot-access-docker-api","errorCode":null,"errorMessage":"docker.sock not mounted, cannot access Docker API","messagePattern":"docker\\.sock not mounted, cannot access Docker API","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/dockerapi/dockerapi.go","lineNumber":268,"sourceCode":"type HostCommandResult struct {\n\tExitCode int    `json:\"exit_code\"` // Command exit status code\n\tOutput   string `json:\"output\"`    // Command output\n\tError    string `json:\"error\"`     // Execution error\n\tDuration int64  `json:\"duration\"`  // Execution time (milliseconds)\n}\n\n// ExecHostCommand executes a command on the host through Docker API\n// Principle: Creates a temporary privileged container mounting the host's root directory,\n// executing commands inside the container that actually operate on the host's file system\nfunc (d *DockerAPI) ExecHostCommand(ctx context.Context, command []string) (*HostCommandResult, error) {\n\tstartTime := time.Now()\n\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}","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/dockerapi/dockerapi.go#L250-L286","documentation":"ExecHostCommand runs host-side commands by spawning a throwaway alpine container with the host's docker.sock bind-mounted. Before doing anything it stats /var/run/docker.sock; if the socket isn't mounted into the calling container, the Docker API is unreachable for this trick and the error is returned with a -1 exit code.","triggerScenarios":"Calling ExecHostCommand / ExecHostShellCommand (or RBAC firewall helpers addNewRules / deleteOldRules) from inside a container started without `-v /var/run/docker.sock:/var/run/docker.sock`.","commonSituations":"Deploying the app container with a trimmed compose file that omits the docker.sock volume; hardened/K8s deployments that forbid socket mounting; socket path remapped to a nonstandard location.","solutions":["Mount the Docker socket: add `-v /var/run/docker.sock:/var/run/docker.sock` to the container run command or volumes in compose","If socket is at a custom path, mount it to /var/run/docker.sock inside the container","On K8s, use a hostPath volume (with the security tradeoffs that entails) or replace the feature with an explicit Docker API client pointing at DOCKER_HOST","Move the firewall-rule logic to a host-level sidecar/service if socket mounting is disallowed"],"exampleFix":"// before (docker-compose.yml)\napp:\n  # no volumes\n// after\napp:\n  volumes:\n    - /var/run/docker.sock:/var/run/docker.sock","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(\"/var/run/docker.sock\"); err != nil {\n    return fmt.Errorf(\"docker.sock unavailable, mount it before use: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"res, err := api.ExecHostCommand(ctx, cmd)\nif err != nil && strings.Contains(err.Error(), \"docker.sock not mounted\") {\n    return fmt.Errorf(\"deploy without docker.sock volume; host command unavailable: %w\", err)\n}","preventionTips":["Always mount /var/run/docker.sock in the app container","Check socket presence at container startup, not at call time","Document the required volume in deployment templates","Consider a dedicated host-command sidecar if socket mounting is restricted"],"tags":["docker","deployment","socket"],"backgroundTag":"docker-socket-not-mounted","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}