Introduction
I'm attempting to use the following version of docker on a Linux VM (uname -a returns Linux xen 4.1.17-yocto-standard #1 SMP PREEMPT Thu Jun 2 13:29:47 PDT 2016 x86_64 GNU/Linux), built from the docker_git BitBake recipe.
If I try to run docker version, I get the following output:
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.3
Git commit (client): 7c8fca2-dirty
OS/Arch (client): linux/amd64
Then the command hangs.
What it should look like
I tried executing docker version on a working docker install (Ubuntu 14.04), and I get the following output:
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.2.1
Git commit (client): 7c8fca2
OS/Arch (client): linux/amd64
Server version: 1.6.2
Server API version: 1.18
Go version (server): go1.2.1
Git commit (server): 7c8fca2
OS/Arch (server): linux/amd64
So, I'm assuming that there's some sort of error when fetching server info.
Additional Research
I'm not familiar with Go, so this section may be cringe-inducing as I try to figure out what the heck is going on here.
I started looking at this portion of api/client/version.go of the Docker source code:
var versionTemplate = `Client:
Version: {{.Client.Version}}
API version: {{.Client.APIVersion}}
Go version: {{.Client.GoVersion}}
Git commit: {{.Client.GitCommit}}
Built: {{.Client.BuildTime}}
OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .Client.Experimental}}
Experimental: {{.Client.Experimental}}{{end}}{{if .ServerOK}}
Server:
Version: {{.Server.Version}}
API version: {{.Server.APIVersion}}
Go version: {{.Server.GoVersion}}
Git commit: {{.Server.GitCommit}}
Built: {{.Server.BuildTime}}
OS/Arch: {{.Server.Os}}/{{.Server.Arch}}{{if .Server.Experimental}}
Experimental: {{.Server.Experimental}}{{end}}{{end}}`
it continues onto this section:
vd := types.VersionResponse{
Client: &types.Version{
Version: dockerversion.Version,
APIVersion: cli.client.ClientVersion(),
GoVersion: runtime.Version(),
GitCommit: dockerversion.GitCommit,
BuildTime: dockerversion.BuildTime,
Os: runtime.GOOS,
Arch: runtime.GOARCH,
Experimental: utils.ExperimentalBuild(),
},
}
From engine-api/types/client.go:
// VersionResponse holds version information for the client and the server
type VersionResponse struct {
Client *Version
Server *Version
}
So all that needs to be done at this point is assign something to the Server member (of type *Version). This happens in the section following the vd assignment from above:
serverVersion, err := cli.client.ServerVersion(context.Background())
if err == nil {
vd.Server = &serverVersion
}
The function definition for ServerVersion is the following from engine-api/client/version.go
// ServerVersion returns information of the docker client and server host.
func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
resp, err := cli.get(ctx, "/version", nil, nil)
if err != nil {
return types.Version{}, err
}
var server types.Version
err = json.NewDecoder(resp.body).Decode(&server)
ensureReaderClosed(resp)
return server, err
}
From what I can gather, the above get function call points to client/request.go from Docker's engine API repo
// getWithContext sends an http request to the docker API using the method GET with a specific go context.
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "GET", path, query, nil, headers)
}
Where:
ctxiscontext.Background()pathis/version- no
query - no
headers
And this documentation for sendRequest from vendor/src/google.golang.org/grpc/call.go:
// sendRequest writes out various information of an RPC such as Context and Message.
func sendRequest(ctx context.Context, codec Codec, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) {
stream, err := t.NewStream(ctx, callHdr)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
if _, ok := err.(transport.ConnectionError); !ok {
t.CloseStream(stream, err)
}
}
}()
// TODO(zhaoq): Support compression.
outBuf, err := encode(codec, args, compressionNone)
if err != nil {
return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err)
}
err = t.Write(stream, outBuf, opts)
if err != nil {
return nil, err
}
// Sent successfully.
return stream, nil
}
This has been guesswork for a while and I'm now concerned that I may be looking in the wrong place.
Questions
- What's causing
docker version,docker run hello-world,docker images,docker ps, anddocker infoto hang and how can it be fixed? - Or, is there a more effective way to inspect the cause of this error?