Einführung
Ich versuche, die folgende Version von docker
auf einer Linux-VM zu verwenden ( uname -a
Rückgabe Linux xen 4.1.17-yocto-standard #1 SMP PREEMPT Thu Jun 2 13:29:47 PDT 2016 x86_64 GNU/Linux)
, erstellt aus dem docker_git
BitBake-Rezept) .
Wenn ich versuche zu laufen docker version
, erhalte ich die folgende Ausgabe:
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
Dann hängt der Befehl.
Wie es aussehen soll
Ich habe versucht, docker version
auf einer funktionierenden Docker-Installation (Ubuntu 14.04) auszuführen , und erhalte die folgende Ausgabe:
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
Ich gehe also davon aus, dass beim Abrufen der Serverinformationen ein Fehler auftritt.
Zusätzliche Forschung
Ich bin nicht mit Go vertraut, daher kann dieser Abschnitt erschütternd sein, wenn ich versuche herauszufinden, was zum Teufel hier vor sich geht.
Ich fing an, mir diesen Teil des api/client/version.go
Docker-Quellcodes anzusehen:
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}}`
Es geht weiter zu diesem Abschnitt:
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(),
},
}
Von engine-api/types/client.go
:
// VersionResponse holds version information for the client and the server
type VersionResponse struct {
Client *Version
Server *Version
}
An dieser Stelle müssen Sie dem Server
Mitglied (vom Typ *Version
) lediglich etwas zuweisen . Dies geschieht in dem Abschnitt nach der vd
Zuordnung von oben:
serverVersion, err := cli.client.ServerVersion(context.Background())
if err == nil {
vd.Server = &serverVersion
}
Die Funktionsdefinition für ServerVersion
ist die folgende vonengine-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
}
Soweit ich das beurteilen kann, get
verweist der obige Funktionsaufruf auf client/request.go
Dockers 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)
}
Woher:
ctx
istcontext.Background()
path
ist/version
- Nein
query
- Nein
headers
Und diese Dokumentation für sendRequest
von 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
}
Dies ist seit einiger Zeit eine Vermutung und ich mache mir jetzt Sorgen, dass ich möglicherweise am falschen Ort suche.
Fragen
- Was verursacht
docker version
,docker run hello-world
,docker images
,docker ps
, unddocker info
hängen und wie sie behoben werden? - Oder gibt es eine effektivere Möglichkeit, die Ursache dieses Fehlers zu untersuchen?
This package contains the daemon and client. Using docker.io on non-amd64 hosts is not supported at this time.
Sind Sie sicher, dass Sie es auf einem AMD-Prozessor und nicht auf Intel ausführen?strace
den Prozess / Daemon verwenden, der den Socket überwacht/var/run/docker.sock
. Ihrdocker info
Befehl hat eine Anforderung an den Socket gesendet, die mit "GET /v1.18/info HTTP / 1.1 \ r \ nHost:" beginnt, und hat ewig auf eine Antwort gewartet, aber der Server hat nicht geantwortet.Antworten:
In Ihrer
strace
Ausgabe wird dringend empfohlen, dass der Docker-Client nicht mit dem Docker-Daemon kommunizieren kann, der standardmäßig einen Socket unter erstellt/var/run/docker.sock
.Der Docker-Daemon sollte ein Systemdienst sein (auf systemd, in
/lib/systemd/system/docker.service
der Socket-Konfiguration unter/lib/systemd/system/docker.socket
), kann jedoch unabhängig mit gestartet werden,/usr/bin/docker daemon
gefolgt von optionalen Optionen.Sie sollten
strace
den Daemon und nicht den Client .Verwendung
strace
auf dem Docker-DaemonRufen Sie die Prozess-ID Ihres Docker-Daemons ab. Jeder dieser Befehle würde die PID in einer aufgerufenen Variablen speichern
$DOCKER_PID
.Direkt aus der Steckdose:
systemd:
Andere:
Verwenden Sie
strace
auf dem Docker-Daemon jetzt, da Sie die PID haben:Führen Sie in einem separaten Terminal einen Befehl aus, der normalerweise im Docker-Client hängt.
Beobachten Sie den
strace
On-the-Docker-Daemon, um zu sehen, was ab dem hörenden Ende des Sockets geschieht.Interpretation der
strace
AusgabeHier ist, was der Daemon tun soll, wenn Sie ausführen
docker version
:Lesen Sie, was der Kunde gesendet hat:
Sammeln Sie Informationen über das System:
Antworte dem Kunden mit Informationen über das System:
Der Client (
docker version
) zeigt dann die Informationen an, die der Server zurückgegeben hat:In Ihrem Problem hat Ihr Docker-Daemon anscheinend Schritt 3 nicht ausgeführt, da der Client in diesem Fall die Antwort gesehen hätte, der Client jedoch nichts erhalten hat.
Anhand dieser Informationen sollten Sie herausfinden können, warum der Docker-Dämon nicht auf Anforderungen des Clients antwortet.
Mögliche Ursachen
Die von Ihnen bereitgestellten Informationen reichen nicht aus, um die Ursache für die Unfähigkeit Ihres Docker-Clients zu ermitteln, eine Antwort vom Docker-Daemon zu erhalten. Hier jedoch einige Tipps:
sudo docker daemon
/var/run/docker.sock
?sudo lsof -p $DOCKER_PID
sollte/var/run/docker.sock type=STREAM
dort irgendwo " " anzeigen.strace
Wenn Sie im of-Daemon keine HTTP-GET-Anforderung vom Client erhalten, bedeutet dies, dass der Server nichts vom Socket empfangen hat.docker version
in den und zu sehenstrace
von dem Dämon , dass es keine waruname()
Anruf, hat der Dämon nicht einmal versuchen , Informationen über das System zu holen.write()
Aufruf imstrace
des Dämons sehen, bedeutet dies, dass der Dämon geantwortet hat, der Client ihn jedoch nicht gesehen hat.quelle
docker
ich nur den TCP-Socket abhörte und nicht den docker.sock. Ich wurde verrückt, bis ich das verstand (danke für deine vollständige Antwort, die mir sehr hilft). Überprüfen Sie Ihre/etc/sysconfig/docker-network
, um sicherzustellen, dass Sie-H unix:///var/run/docker.sock