in executors/docker/docker.go [995:1074]
func (e *executor) connectDocker(options common.ExecutorPrepareOptions) error {
var opts []client.Opt
creds := e.Config.Docker.Credentials
environment, ok := e.Build.ExecutorData.(executors.Environment)
if ok {
c, err := environment.Prepare(e.Context, e.BuildLogger, options)
if err != nil {
return fmt.Errorf("preparing environment: %w", err)
}
if e.tunnelClient != nil {
e.tunnelClient.Close()
}
e.tunnelClient = c
// We tunnel the docker connection for remote environments.
//
// To do this, we create a new dial context for Docker's client, whilst
// also overridding the daemon hostname it would typically use (if it were to use
// its own dialer).
host := creds.Host
scheme, dialer, err := e.environmentDialContext(c, host)
if err != nil {
return fmt.Errorf("creating env dialer: %w", err)
}
// If the scheme (docker uses it to define the protocol used) is "npipe" or "unix", we
// need to use a "fake" host, otherwise when dialing from Linux to Windows or vice-versa
// docker will complain because it doesn't think Linux can support "npipe" and doesn't
// think Windows can support "unix".
switch scheme {
case "unix", "npipe", "dial-stdio":
creds.Host = internalFakeTunnelHostname
}
opts = append(opts, client.WithDialContext(dialer))
}
dockerClient, err := docker.New(creds, opts...)
if err != nil {
return err
}
e.client = dockerClient
e.info, err = e.client.Info(e.Context)
if err != nil {
return err
}
serverVersion, err := e.client.ServerVersion(e.Context)
if err != nil {
return fmt.Errorf("getting server version info: %w", err)
}
e.serverAPIVersion, err = version.NewVersion(serverVersion.APIVersion)
if err != nil {
return fmt.Errorf("parsing server API version %q: %w", serverVersion.APIVersion, err)
}
e.BuildLogger.Debugln(fmt.Sprintf(
"Connected to docker daemon (client version: %s, server version: %s, api version: %s, kernel: %s, os: %s/%s)",
e.client.ClientVersion(),
e.info.ServerVersion,
serverVersion.APIVersion,
e.info.KernelVersion,
e.info.OSType,
e.info.Architecture,
))
err = e.validateOSType()
if err != nil {
return err
}
e.waiter = wait.NewDockerKillWaiter(e.client)
return err
}