func()

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
}