Created
March 30, 2022 13:25
-
-
Save wagoodman/f66c9003daa4c472ac2a5eb2f28a9f7f to your computer and use it in GitHub Desktop.
docker auth issue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"context" | |
"encoding/base64" | |
"encoding/json" | |
"fmt" | |
"io" | |
"net/http" | |
"os" | |
"strings" | |
"github.com/docker/cli/cli/config" | |
configTypes "github.com/docker/cli/cli/config/types" | |
"github.com/docker/cli/cli/connhelper" | |
"github.com/docker/docker/api/types" | |
"github.com/docker/docker/client" | |
"github.com/google/go-containerregistry/pkg/name" | |
) | |
func getClient() (*client.Client, error) { | |
var clientOpts = []client.Opt{ | |
client.FromEnv, | |
client.WithAPIVersionNegotiation(), | |
} | |
host := os.Getenv("DOCKER_HOST") | |
if strings.HasPrefix(host, "ssh") { | |
var ( | |
helper *connhelper.ConnectionHelper | |
err error | |
) | |
helper, err = connhelper.GetConnectionHelper(host) | |
if err != nil { | |
return nil, fmt.Errorf("failed to fetch docker connection helper: %w", err) | |
} | |
clientOpts = append(clientOpts, func(c *client.Client) error { | |
httpClient := &http.Client{ | |
Transport: &http.Transport{ | |
DialContext: helper.Dialer, | |
}, | |
} | |
return client.WithHTTPClient(httpClient)(c) | |
}) | |
clientOpts = append(clientOpts, client.WithHost(helper.Host)) | |
clientOpts = append(clientOpts, client.WithDialContext(helper.Dialer)) | |
} | |
if os.Getenv("DOCKER_TLS_VERIFY") != "" && os.Getenv("DOCKER_CERT_PATH") == "" { | |
err := os.Setenv("DOCKER_CERT_PATH", "~/.docker") | |
if err != nil { | |
return nil, fmt.Errorf("failed create docker client: %w", err) | |
} | |
} | |
dockerClient, err := client.NewClientWithOpts(clientOpts...) | |
if err != nil { | |
return nil, fmt.Errorf("failed create docker client: %w", err) | |
} | |
return dockerClient, nil | |
} | |
type pullEvent struct { | |
ID string `json:"id"` | |
Status string `json:"status"` | |
Error string `json:"error,omitempty"` | |
Progress string `json:"progress,omitempty"` | |
ProgressDetail struct { | |
Current int `json:"current"` | |
Total int `json:"total"` | |
} `json:"progressDetail"` | |
} | |
func main() { | |
imageStr := "alpine:latest" | |
c, err := getClient() | |
if err != nil { | |
panic(err) | |
} | |
var options = types.ImagePullOptions{} | |
cfg, err := config.Load("") | |
if err != nil { | |
panic(fmt.Errorf("failed to load docker config: %w", err)) | |
} | |
ref, err := name.ParseReference(imageStr) | |
if err != nil { | |
panic(err) | |
} | |
hostname := ref.Context().RegistryStr() | |
authConfig, err := cfg.GetAuthConfig(hostname) | |
if err != nil { | |
panic(err) | |
} | |
options.RegistryAuth, err = encodeCredentials(authConfig) | |
if err != nil { | |
fmt.Printf("WARN: bad auth encode: %+v", err) | |
} | |
resp, err := c.ImagePull(context.Background(), imageStr, options) | |
if err != nil { | |
panic(fmt.Errorf("pull failed: %w", err)) | |
} | |
var thePullEvent *pullEvent | |
decoder := json.NewDecoder(resp) | |
for { | |
if err := decoder.Decode(&thePullEvent); err != nil { | |
if err == io.EOF { | |
break | |
} | |
panic(fmt.Errorf("failed to pull image: %w", err)) | |
} | |
fmt.Printf("%+v\n====\n", thePullEvent) | |
} | |
fmt.Println("complete!") | |
} | |
func encodeCredentials(authConfig configTypes.AuthConfig) (string, error) { | |
buffer := &bytes.Buffer{} | |
encoder := json.NewEncoder(buffer) | |
// note: the contents may contain characters that should not be escaped (such as password contents) | |
encoder.SetEscapeHTML(false) | |
if err := encoder.Encode(authConfig); err != nil { | |
return "", err | |
} | |
return base64.URLEncoding.EncodeToString(buffer.Bytes()), nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment