Skip to content

Commit

Permalink
Honor the host specified in current docker context
Browse files Browse the repository at this point in the history
Big shoutout to Rajiv Kushwaha and his contribution in lazydocker (wagoodman#464)
 from where I have taken this code.
  • Loading branch information
mark2185 committed Dec 22, 2023
1 parent 3ef1dd2 commit fe907a6
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 225 deletions.
81 changes: 81 additions & 0 deletions dive/image/docker/engine_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import (
"io"
"net/http"
"os"
"runtime"
"strings"

cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/connhelper"
ddocker "github.com/docker/cli/cli/context/docker"
ctxstore "github.com/docker/cli/cli/context/store"
"github.com/docker/docker/client"
"golang.org/x/net/context"

Expand Down Expand Up @@ -42,6 +46,77 @@ func (r *engineResolver) Build(args []string) (*image.Image, error) {
return r.Fetch(id)
}

// determineDockerHost tries to determine the docker host that we should connect to
// in the following order of decreasing precedence:
// - value of the "DOCKER_HOST" environment variable
// - host retrieved from the current context (specified via DOCKER_CONTEXT)
// - "default docker host" for the host operating system, otherwise
func determineDockerHost() (string, error) {
// if the docker host is explicitly set via the "DOCKER_HOST" environment variable,
// then it's a no-brainer :shrug:
if host := os.Getenv("DOCKER_HOST"); len(host) > 0 {
return host, nil
}

currentContext := os.Getenv("DOCKER_CONTEXT")
if len(currentContext) == 0 {
dockerConfigDir := cliconfig.Dir()
if _, err := os.Stat(dockerConfigDir); err != nil {
return "", err
}
cf, err := cliconfig.Load(dockerConfigDir)
if err != nil {
return "", err
}
currentContext = cf.CurrentContext
}
if len(currentContext) == 0 {
// if a docker context is neither specified via the "DOCKER_CONTEXT" environment variable nor via the
// $HOME/.docker/config file, then we fall back to connecting to the "default docker host" meant for
// the host operating system
if runtime.GOOS == "windows" {
return "npipe:////./pipe/docker_engine", nil
} else {
return "unix:///var/run/docker.sock", nil
}
}

storeConfig := ctxstore.NewConfig(
func() interface{} { return &ddocker.EndpointMeta{} },
ctxstore.EndpointTypeGetter(ddocker.DockerEndpoint, func() interface{} { return &ddocker.EndpointMeta{} }),
)

st := ctxstore.New(cliconfig.ContextStoreDir(), storeConfig)
md, err := st.GetMetadata(currentContext)
if err != nil {
return "", err
}
dockerEP, ok := md.Endpoints[ddocker.DockerEndpoint]
if !ok {
return "", err
}
dockerEPMeta, ok := dockerEP.(ddocker.EndpointMeta)
if !ok {
return "", fmt.Errorf("expected docker.EndpointMeta, got %T", dockerEP)
}

if dockerEPMeta.Host != "" {
return dockerEPMeta.Host, nil
}

// we might end up here if the context was created with the `host` set to an empty value (i.e. '')
// for example:
// ```sh
// docker context create foo --docker "host="
// ```
// in such a scenario, we mimic the `docker` cli and try to connect to the "default docker host"
if runtime.GOOS == "windows" {
return "npipe:////./pipe/docker_engine", nil
} else {
return "unix:///var/run/docker.sock", nil
}
}

func (r *engineResolver) fetchArchive(id string) (io.ReadCloser, error) {
var err error
var dockerClient *client.Client
Expand Down Expand Up @@ -70,15 +145,21 @@ func (r *engineResolver) fetchArchive(id string) (io.ReadCloser, error) {
clientOpts = append(clientOpts, client.WithDialContext(helper.Dialer))

default:
dockerHost, err := determineDockerHost()
if err != nil {
fmt.Printf("Could not determine host %v", err)
}

if os.Getenv("DOCKER_TLS_VERIFY") != "" && os.Getenv("DOCKER_CERT_PATH") == "" {
os.Setenv("DOCKER_CERT_PATH", "~/.docker")
}

clientOpts = append(clientOpts, client.FromEnv)
clientOpts = append(clientOpts, client.WithHost(dockerHost))
}

clientOpts = append(clientOpts, client.WithAPIVersionNegotiation())

dockerClient, err = client.NewClientWithOpts(clientOpts...)
if err != nil {
return nil, err
Expand Down
78 changes: 43 additions & 35 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,64 @@ require (
github.com/awesome-gocui/gocui v1.1.0
github.com/awesome-gocui/keybinding v1.0.1-0.20190805183143-864552bd36b7
github.com/cespare/xxhash v1.1.0
github.com/docker/cli v0.0.0-20190906153656-016a3232168d
github.com/docker/docker v24.0.2+incompatible
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.7.0
github.com/google/uuid v1.1.1
github.com/logrusorgru/aurora v0.0.0-20190803045625-94edacc10f9b
github.com/docker/cli v24.0.7+incompatible
github.com/docker/docker v24.0.7+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.16.0
github.com/google/uuid v1.5.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/lunixbochs/vtclean v1.0.0
github.com/mitchellh/go-homedir v1.1.0
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee
github.com/sergi/go-diff v1.0.0
github.com/sirupsen/logrus v1.4.2
github.com/spf13/afero v1.2.2
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.4.0
golang.org/x/net v0.11.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.18.2
golang.org/x/net v0.19.0
)

require (
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.4.7 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/gdamore/tcell/v2 v2.4.0 // indirect
github.com/gdamore/tcell/v2 v2.7.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
github.com/magiconair/properties v1.8.1 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.1.0 // indirect
github.com/spf13/cast v1.3.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.4.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
gotest.tools v2.2.0+incompatible // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.16.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.0 // indirect
)
Loading

0 comments on commit fe907a6

Please sign in to comment.