Docker Engine SDKでリモートのDocker daemonにSSH経由で接続する
以前の記事でDocker Engine SDKの使い方について解説しました。この頃 (2020/12) はビルドに少し工夫 が必要でしたが、今 (2022/09) では go mod tidy
で用意された go.mod でそのままビルドできるようになっていました。
この記事では、Docker Engine SDKを使って、リモートサーバー上のDocker daemonにSSH経由で接続する方法について書きます。
haibara-works.hatenablog.com
結論
下記のコードは、ssh://user@example.com で示されるサーバー上にあるDocker daemonに接続してimageを一覧表示するサンプルです。
ポイントは github.com/docker/cli/cli/connhelper
をimportしていることです。
package main import ( "context" "fmt" "net/http" "github.com/docker/cli/cli/connhelper" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() opts, err := withSSHConn("ssh://user@example.com") if err != nil { panic(err.Error()) } cli, err := client.NewClientWithOpts(opts...) if err != nil { panic(err.Error()) } images, err := cli.ImageList(ctx, types.ImageListOptions{}) if err != nil { panic(err.Error()) } for _, image := range images { fmt.Println(image.RepoTags) } } func withSSHConn(host string) ([]client.Opt, error) { helper, err := connhelper.GetConnectionHelper(host) if err != nil { return nil, err } httpClient := &http.Client{ Transport: &http.Transport{ DialContext: helper.Dialer, }, } return []client.Opt{ client.WithHTTPClient(httpClient), client.WithHost(helper.Host), client.WithDialContext(helper.Dialer), }, nil }
失敗した方法
docker
コマンドを使ってSSH経由でリモートのdaemonに接続するには、以下のようにcontextを作成します。
$ docker context create ssh-to-server --docker "host=ssh://user@example.com" $ docker context use ssh-to-server # リモートのdaemonに対する操作 $ docker image ls
Protect the Docker daemon socket | Docker Documentation
Docker Engine SDKでもこれと同様にできるかなと思い、以下のようにclient.NewClientWithOpts
に渡すWithHost
でSSHのURLを指定していました。
cli, err := client.NewClientWithOpts(client.WithHost("ssh://user@example.com"))
しかしこれでは上手くいかず、下記のエラーが発生します。
error during connect: Get "http://user%40example.com/v1.41/images/json": dial tcp: lookup user@example.com: no such host