Skip to content

Unable to talk to docker daemon through sock file #2021

Open
@bialasjaroslaw

Description

@bialasjaroslaw

I was trying to use cpp-httplib to communicate with my local docker daemon using sock file. There is a possibility to do that according to this

After testing my connection with curl I was pretty sure that it will be easy to do however problem (IMO) is caused by the fact that docker engine is expecting to receive request on endpoint http://localhost/v1.39/images/json and not /v1.39/images/json. I can not see how to do that using httplib::Client object because its only argument is a path to sock file.

Also curl is working with that socket curl --unix-socket /run/docker.sock /v1.39/images/json

I am attaching a short example comparing httplib and raw socket usage

#if defined(HTTP_LIB)
#include <httplib.h>
#include <iostream>
#include <sys/socket.h>
#else
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>
#endif

int main(){
    std::string dockerSocket("/run/docker.sock");
    std::string endpoint("http://localhost/v1.39/images/json");
    #if defined(HTTP_LIB)
        httplib::Client cli(dockerSocket);
        cli.set_address_family(AF_UNIX);
        auto res = cli.Get(endpoint);
        if (res && res->status == 200) {
            std::cout << "Response from Docker Engine: "<< res->body << std::endl;
        } else {
            if (res) {
                std::cout << "HTTP Error: " << res->status << std::endl;
            } else {
                std::cout << "Connection failed: " << httplib::to_string(res.error()) << std::endl;
            }
        }
    #else
        int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
        try{
            const char* data = "GET http://localhost/v1.39/images/json HTTP/1.1\r\n"
                "Host: localhost\r\n"
                "Connection: close\r\n\r\n";
            if (sockfd < 0) {
                throw std::runtime_error("Failed to create socket");
            }
            sockaddr_un addr{};
            addr.sun_family = AF_UNIX;
            std::strncpy(addr.sun_path, dockerSocket.c_str(), sizeof(addr.sun_path) - 1);
            if (connect(sockfd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0) {
                throw std::runtime_error("Failed to connect to the socket");
            }
            if (send(sockfd, data, strlen(data), 0) < 0) {
                throw std::runtime_error("Failed to send data");
            }
            char buffer[4096] = {};
            while(true)
            {   
                ssize_t bytesReceived = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
                if (bytesReceived <= 0) {
                    break;
                }
                buffer[bytesReceived] = '\0';
                std::cout << buffer << std::endl;
            }
        }
        catch(const std::exception &ex){
            std::cout << "Error: " << ex.what() << std::endl;
        }
        if (sockfd >= 0){
            close(sockfd);
        }
    #endif

    return 0;
}

g++ example.cpp && ./a.out

HTTP/1.1 200 OK
Api-Version: 1.46
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/27.1.2 (linux)
Date: Tue, 14 Jan 2025 17:08:12 GMT
Connection: close
Transfer-Encoding: chunked

f6b

g++ example.cpp -DHTTP_LIB && ./a.out

HTTP Error: 400

I am using httplib 0.18.3 from vcpkg, but I also tried with trunk version. My GCC is 14.2.1 and Docker 27.1.2

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions