// LoadAndGetImageRegistryAuth loads the set of client auth objects from a docker config file // and returns the appropriate client auth object for a given image name. func LoadAndGetImageRegistryAuth(dockerCfg io.Reader, imageName string) client.AuthConfiguration { auths, err := client.NewAuthConfigurations(dockerCfg) if err != nil { glog.V(0).Infof("error: Unable to load docker config") return client.AuthConfiguration{} } return GetImageRegistryAuth(auths, imageName) }
// LoadImageRegistryAuth loads and returns the set of client auth objects from a docker config // json file. func LoadImageRegistryAuth(dockerCfg io.Reader) *client.AuthConfigurations { auths, err := client.NewAuthConfigurations(dockerCfg) if err != nil { glog.V(0).Infof("error: Unable to load docker config") return nil } return auths }
// setupPullSecret provides a Docker authentication configuration when the // PullSecret is specified. func (d *DockerBuilder) setupPullSecret() (*docker.AuthConfigurations, error) { if len(os.Getenv(dockercfg.PullAuthType)) == 0 { return nil, nil } r, err := os.Open(os.Getenv(dockercfg.PullAuthType)) if err != nil { return nil, fmt.Errorf("'%s': %s", os.Getenv(dockercfg.PullAuthType), err) } return docker.NewAuthConfigurations(r) }
// setupPullSecret provides a Docker authentication configuration when the // PullSecret is specified. func (d *DockerBuilder) setupPullSecret() (*docker.AuthConfigurations, error) { if len(os.Getenv("PULL_DOCKERCFG_PATH")) == 0 { return nil, nil } r, err := os.Open(os.Getenv("PULL_DOCKERCFG_PATH")) if err != nil { return nil, fmt.Errorf("'%s': %s", os.Getenv("PULL_DOCKERCFG_PATH"), err) } return docker.NewAuthConfigurations(r) }
// DockerPush is the cli action for 'godo docker-push' func DockerPush(c *cli.Context) { dockerClient := dockutil.ClientOrDie() cfg := config.ReadOrDie(c.String(FlagConfigFile)) if cfg.Docker.ImageName == "" { log.Err("Docker image name was empty") os.Exit(1) } pio := docker.PushImageOptions{ Name: cfg.Docker.ImageName, Tag: cfg.Docker.GetTag(), OutputStream: os.Stdout, } authFileLoc := cfg.Docker.Push.GetAuthFileLocation() authFile, err := os.Open(authFileLoc) if err != nil { log.Err("Reading Docker auth file %s [%s]", authFileLoc, err) os.Exit(1) } defer func() { if err := authFile.Close(); err != nil { log.Err("Closing Docker auth file %s [%s]", authFileLoc, err) } }() auths, err := docker.NewAuthConfigurations(authFile) if err != nil { log.Err("Parsing auth file %s [%s]", authFileLoc, err) os.Exit(1) } registry := "https://index.docker.io/v1/" spl := strings.Split(pio.Name, "/") if len(spl) == 3 { registry = spl[0] } auth, ok := auths.Configs[registry] if !ok { log.Err("Registry %s in your image %s is not in auth file %s ", registry, pio.Name, authFileLoc) os.Exit(1) } if err := dockerClient.PushImage(pio, auth); err != nil { log.Err("Pushing Docker image %s [%s]", pio.Name, err) os.Exit(1) } log.Info("Successfully pushed Docker image %s:%s", pio.Name, pio.Tag) }
// pullImage creates an image by pulling it from a docker registry func (d *DockerDriver) pullImage(driverConfig *DockerDriverConfig, client *docker.Client, repo string, tag string) error { pullOptions := docker.PullImageOptions{ Repository: repo, Tag: tag, } authOptions := docker.AuthConfiguration{} if len(driverConfig.Auth) != 0 { authOptions = docker.AuthConfiguration{ Username: driverConfig.Auth[0].Username, Password: driverConfig.Auth[0].Password, Email: driverConfig.Auth[0].Email, ServerAddress: driverConfig.Auth[0].ServerAddress, } } if authConfigFile := d.config.Read("docker.auth.config"); authConfigFile != "" { if f, err := os.Open(authConfigFile); err == nil { defer f.Close() var authConfigurations *docker.AuthConfigurations if authConfigurations, err = docker.NewAuthConfigurations(f); err != nil { return fmt.Errorf("Failed to create docker auth object: %v", err) } authConfigurationKey := "" if driverConfig.SSL { authConfigurationKey += "https://" } authConfigurationKey += strings.Split(driverConfig.ImageName, "/")[0] if authConfiguration, ok := authConfigurations.Configs[authConfigurationKey]; ok { authOptions = authConfiguration } else { d.logger.Printf("[INFO] Failed to find docker auth with key %s", authConfigurationKey) } } else { return fmt.Errorf("Failed to open auth config file: %v, error: %v", authConfigFile, err) } } err := client.PullImage(pullOptions, authOptions) if err != nil { d.logger.Printf("[ERR] driver.docker: failed pulling container %s:%s: %s", repo, tag, err) return d.recoverablePullError(err, driverConfig.ImageName) } d.logger.Printf("[DEBUG] driver.docker: docker pull %s:%s succeeded", repo, tag) return nil }
// setupPullSecret provides a Docker authentication configuration when the // PullSecret is specified. func (d *DockerBuilder) setupPullSecret() (*docker.AuthConfigurations, error) { if len(os.Getenv(dockercfg.PullAuthType)) == 0 { return nil, nil } glog.V(0).Infof("Checking for Docker config file for %s in path %s", dockercfg.PullAuthType, os.Getenv(dockercfg.PullAuthType)) dockercfgPath := dockercfg.GetDockercfgFile(os.Getenv(dockercfg.PullAuthType)) if len(dockercfgPath) == 0 { return nil, fmt.Errorf("no docker config file found in '%s'", os.Getenv(dockercfg.PullAuthType)) } glog.V(0).Infof("Using Docker config file %s", dockercfgPath) r, err := os.Open(dockercfgPath) if err != nil { return nil, fmt.Errorf("'%s': %s", dockercfgPath, err) } return docker.NewAuthConfigurations(r) }
func GetImageRegistryAuth(dockerCfg io.Reader, imageName string) client.AuthConfiguration { spec, err := ParseDockerImageReference(imageName) if err != nil { return client.AuthConfiguration{} } if auths, err := client.NewAuthConfigurations(dockerCfg); err == nil { if auth, ok := auths.Configs[spec.Registry]; ok { glog.V(5).Infof("Using %s[%s] credentials for pulling %s", auth.Email, spec.Registry, imageName) return auth } if auth, ok := auths.Configs[defaultRegistry]; ok { glog.V(5).Infof("Using %s credentials for pulling %s", auth.Email, imageName) return auth } } return client.AuthConfiguration{} }
func appendDockerCfgConfigs(dockercfg string, cfgs *docker.AuthConfigurations) error { var imagePullAuths *docker.AuthConfigurations reader, err := os.Open(dockercfg) if err != nil { return fmt.Errorf("Unable to open docker config file: %v\n", err) } defer reader.Close() if imagePullAuths, err = docker.NewAuthConfigurations(reader); err != nil { return fmt.Errorf("Unable to parse docker config file: %v\n", err) } if len(imagePullAuths.Configs) == 0 { return fmt.Errorf("No auths were found in the given dockercfg file\n") } for name, ac := range imagePullAuths.Configs { cfgs.Configs[fmt.Sprintf("%s/%s", dockercfg, name)] = ac } return nil }
func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { var driverConfig DockerDriverConfig if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil { return nil, err } image := driverConfig.ImageName if err := driverConfig.Validate(); err != nil { return nil, err } if task.Resources == nil { return nil, fmt.Errorf("Resources are not specified") } if task.Resources.MemoryMB == 0 { return nil, fmt.Errorf("Memory limit cannot be zero") } if task.Resources.CPU == 0 { return nil, fmt.Errorf("CPU limit cannot be zero") } cleanupContainer := d.config.ReadBoolDefault("docker.cleanup.container", true) cleanupImage := d.config.ReadBoolDefault("docker.cleanup.image", true) // Initialize docker API client client, err := d.dockerClient() if err != nil { return nil, fmt.Errorf("Failed to connect to docker daemon: %s", err) } repo, tag := docker.ParseRepositoryTag(image) // Make sure tag is always explicitly set. We'll default to "latest" if it // isn't, which is the expected behavior. if tag == "" { tag = "latest" } var dockerImage *docker.Image // We're going to check whether the image is already downloaded. If the tag // is "latest" we have to check for a new version every time so we don't // bother to check and cache the id here. We'll download first, then cache. if tag != "latest" { dockerImage, err = client.InspectImage(image) } // Download the image if dockerImage == nil { pullOptions := docker.PullImageOptions{ Repository: repo, Tag: tag, } authOptions := docker.AuthConfiguration{} if len(driverConfig.Auth) != 0 { authOptions = docker.AuthConfiguration{ Username: driverConfig.Auth[0].Username, Password: driverConfig.Auth[0].Password, Email: driverConfig.Auth[0].Email, ServerAddress: driverConfig.Auth[0].ServerAddress, } } if authConfig := d.config.Read("docker.auth.config"); authConfig != "" { if f, err := os.Open(authConfig); err == nil { defer f.Close() if authConfigurations, err := docker.NewAuthConfigurations(f); err == nil { if authConfiguration, ok := authConfigurations.Configs[repo]; ok { authOptions = authConfiguration } } } } err = client.PullImage(pullOptions, authOptions) if err != nil { d.logger.Printf("[ERR] driver.docker: failed pulling container %s:%s: %s", repo, tag, err) return nil, fmt.Errorf("Failed to pull `%s`: %s", image, err) } d.logger.Printf("[DEBUG] driver.docker: docker pull %s:%s succeeded", repo, tag) // Now that we have the image we can get the image id dockerImage, err = client.InspectImage(image) if err != nil { d.logger.Printf("[ERR] driver.docker: failed getting image id for %s: %s", image, err) return nil, fmt.Errorf("Failed to determine image id for `%s`: %s", image, err) } } taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName] if !ok { return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName) } d.logger.Printf("[DEBUG] driver.docker: identified image %s as %s", image, dockerImage.ID) bin, err := discover.NomadExecutable() if err != nil { return nil, fmt.Errorf("unable to find the nomad binary: %v", err) } pluginLogFile := filepath.Join(taskDir, fmt.Sprintf("%s-syslog-collector.out", task.Name)) pluginConfig := &plugin.ClientConfig{ Cmd: exec.Command(bin, "syslog", pluginLogFile), } logCollector, pluginClient, err := createLogCollector(pluginConfig, d.config.LogOutput, d.config) if err != nil { return nil, err } logCollectorCtx := &logcollector.LogCollectorContext{ TaskName: task.Name, AllocDir: ctx.AllocDir, LogConfig: task.LogConfig, PortLowerBound: d.config.ClientMinPort, PortUpperBound: d.config.ClientMaxPort, } ss, err := logCollector.LaunchCollector(logCollectorCtx) if err != nil { return nil, fmt.Errorf("failed to start syslog collector: %v", err) } config, err := d.createContainer(ctx, task, &driverConfig, ss.Addr) if err != nil { d.logger.Printf("[ERR] driver.docker: failed to create container configuration for image %s: %s", image, err) pluginClient.Kill() return nil, fmt.Errorf("Failed to create container configuration for image %s: %s", image, err) } // Create a container container, err := client.CreateContainer(config) if err != nil { // If the container already exists because of a previous failure we'll // try to purge it and re-create it. if strings.Contains(err.Error(), "container already exists") { // Get the ID of the existing container so we can delete it containers, err := client.ListContainers(docker.ListContainersOptions{ // The image might be in use by a stopped container, so check everything All: true, Filters: map[string][]string{ "name": []string{config.Name}, }, }) if err != nil { d.logger.Printf("[ERR] driver.docker: failed to query list of containers matching name:%s", config.Name) pluginClient.Kill() return nil, fmt.Errorf("Failed to query list of containers: %s", err) } // Couldn't find any matching containers if len(containers) == 0 { d.logger.Printf("[ERR] driver.docker: failed to get id for container %s: %#v", config.Name, containers) pluginClient.Kill() return nil, fmt.Errorf("Failed to get id for container %s", config.Name) } // Delete matching containers d.logger.Printf("[INFO] driver.docker: a container with the name %s already exists; will attempt to purge and re-create", config.Name) for _, container := range containers { err = client.RemoveContainer(docker.RemoveContainerOptions{ ID: container.ID, }) if err != nil { d.logger.Printf("[ERR] driver.docker: failed to purge container %s", container.ID) pluginClient.Kill() return nil, fmt.Errorf("Failed to purge container %s: %s", container.ID, err) } d.logger.Printf("[INFO] driver.docker: purged container %s", container.ID) } container, err = client.CreateContainer(config) if err != nil { d.logger.Printf("[ERR] driver.docker: failed to re-create container %s; aborting", config.Name) pluginClient.Kill() return nil, fmt.Errorf("Failed to re-create container %s; aborting", config.Name) } } else { // We failed to create the container for some other reason. d.logger.Printf("[ERR] driver.docker: failed to create container from image %s: %s", image, err) pluginClient.Kill() return nil, fmt.Errorf("Failed to create container from image %s: %s", image, err) } } d.logger.Printf("[INFO] driver.docker: created container %s", container.ID) // Start the container err = client.StartContainer(container.ID, container.HostConfig) if err != nil { d.logger.Printf("[ERR] driver.docker: failed to start container %s: %s", container.ID, err) pluginClient.Kill() return nil, fmt.Errorf("Failed to start container %s: %s", container.ID, err) } d.logger.Printf("[INFO] driver.docker: started container %s", container.ID) // Return a driver handle h := &DockerHandle{ client: client, logCollector: logCollector, pluginClient: pluginClient, cleanupContainer: cleanupContainer, cleanupImage: cleanupImage, logger: d.logger, imageID: dockerImage.ID, containerID: container.ID, killTimeout: d.DriverContext.KillTimeout(task), doneCh: make(chan struct{}), waitCh: make(chan *cstructs.WaitResult, 1), } go h.run() return h, nil }