func launchContainer(client *docker.Client, containerImageName, name string) (*docker.Container, error) { images, err := client.ListImages(docker.ListImagesOptions{Filter: containerImageName}) if err != nil { return nil, err } targetImageId := images[0].ID container, err := client.CreateContainer(docker.CreateContainerOptions{ Name: name, Config: &docker.Config{ Image: targetImageId, }, }) if err != nil { return nil, err } if err := client.StartContainer(container.ID, &docker.HostConfig{PublishAllPorts: true}); err != nil { return nil, err } return client.InspectContainer(container.ID) }
func checkImages(client *docker.Client, config *Config) error { images, err := client.ListImages(docker.ListImagesOptions{}) if err != nil { log.Fatalln(err) } imagesWithTags := map[string]bool{} for _, image := range images { for _, tag := range image.RepoTags { imagesWithTags[tag] = true } } fmt.Println("checking images...") for _, lang := range Extensions { if imagesWithTags[lang.Image] == true { log.Printf("image %s exists", lang.Image) } else { if config.FetchImages { log.Println("pulling", lang.Image, "image...") err := pullImage(lang.Image, client) if err != nil { log.Fatalln(err) } } else { return fmt.Errorf("image %s does not exist", lang.Image) } } } return nil }
func findImage(client *docker.Client, image string) (*docker.APIImages, error) { images, err := client.ListImages(docker.ListImagesOptions{}) if err != nil { return nil, err } for _, img := range images { for _, t := range img.RepoTags { if t == image { return &img, nil } } } return nil, fmt.Errorf("invalid image:", image) }
func fetchLocalImages(data *Data, client *dc.Client) error { images, err := client.ListImages(dc.ListImagesOptions{All: false}) if err != nil { return fmt.Errorf("Unable to list Docker images: %s", err) } if data.DockerImages == nil { data.DockerImages = make(map[string]*dc.APIImages) } for i, image := range images { data.DockerImages[image.ID[:12]] = &images[i] data.DockerImages[image.ID] = &images[i] for _, repotag := range image.RepoTags { data.DockerImages[repotag] = &images[i] } } return nil }
func fetchLocalImages(data *Data, client *dc.Client) error { images, err := client.ListImages(dc.ListImagesOptions{All: false}) if err != nil { return fmt.Errorf("Unable to list Docker images: %s", err) } if data.DockerImages == nil { data.DockerImages = make(map[string]*dc.APIImages) } // Docker uses different nomenclatures in different places...sometimes a short // ID, sometimes long, etc. So we store both in the map so we can always find // the same image object. We store the tags, too. for i, image := range images { data.DockerImages[image.ID[:12]] = &images[i] data.DockerImages[image.ID] = &images[i] for _, repotag := range image.RepoTags { data.DockerImages[repotag] = &images[i] } } return nil }
func syncImages(client *dockerclient.Client, imageRoot string) error { logrus.Debugf("Syncing images from %s", imageRoot) f, err := os.Open(filepath.Join(imageRoot, "images.json")) if err != nil { return fmt.Errorf("error opening image json file: %v", err) } defer f.Close() var m tagMap if err := json.NewDecoder(f).Decode(&m); err != nil { return fmt.Errorf("error decoding images json: %v", err) } allTags := map[string]struct{}{} neededImages := map[string]struct{}{} for imageID, tags := range m { neededImages[imageID] = struct{}{} for _, t := range tags { allTags[t] = struct{}{} } } images, err := client.ListImages(dockerclient.ListImagesOptions{}) if err != nil { return fmt.Errorf("error listing images: %v", err) } for _, img := range images { expectedTags, ok := m[img.ID] if ok { delete(neededImages, img.ID) repoTags := filterRepoTags(img.RepoTags) logrus.Debugf("Tags for %s: %#v", img.ID, repoTags) // Sync tags for image ID removedTags, addedTags := listDiff(repoTags, expectedTags) for _, t := range addedTags { if err := tagImage(client, img.ID, t); err != nil { return err } } for _, t := range removedTags { // Check if this image tag conflicts with an expected // tag, in which case force tag will update if _, ok := allTags[t]; !ok { logrus.Debugf("Removing tag %s", t) if err := client.RemoveImage(t); err != nil { return fmt.Errorf("error removing tag %s: %v", t, err) } } } } else { removeOptions := dockerclient.RemoveImageOptions{ Force: true, } if err := client.RemoveImageExtended(img.ID, removeOptions); err != nil { return fmt.Errorf("error moving image %s: %v", img.ID, err) } } } for imageID := range neededImages { tags, ok := m[imageID] if !ok { return fmt.Errorf("missing image %s in tag map", imageID) } _, err := client.InspectImage(imageID) if err != nil { tf, err := os.Open(filepath.Join(imageRoot, imageID+".tar")) if err != nil { return fmt.Errorf("error opening image tar %s: %v", imageID, err) } defer tf.Close() loadOptions := dockerclient.LoadImageOptions{ InputStream: tf, } if err := client.LoadImage(loadOptions); err != nil { return fmt.Errorf("error loading image %s: %v", imageID, err) } } for _, t := range tags { if err := tagImage(client, imageID, t); err != nil { return err } } } return nil }
func cleanImages(client *docker.Client) { defer wg.Done() log.Printf("Img Cleanup: the following images will be locked: %s", *pImageLocked) log.Println("Img Cleanup: starting image cleanup ...") for { // imageIdMap[imageID] = isRemovable imageIdMap := make(map[string]bool) // Get the image ID list before the cleanup images, err := client.ListImages(docker.ListImagesOptions{All: false}) if err != nil { log.Println("Img Cleanup: cannot get images list", err) time.Sleep(time.Duration(*pImageCleanInterval+*pImageCleanDelayed) * time.Second) continue } for _, image := range images { imageIdMap[image.ID] = true } // Get the image IDs used by all the containers containers, err := client.ListContainers(docker.ListContainersOptions{All: true}) if err != nil { log.Println("Img Cleanup: cannot get container list", err) time.Sleep(time.Duration(*pImageCleanInterval+*pImageCleanDelayed) * time.Second) continue } else { inspect_error := false for _, container := range containers { containerInspect, err := client.InspectContainer(container.ID) if err != nil { inspect_error = true log.Println("Img Cleanup: cannot get container inspect", err) break } delete(imageIdMap, containerInspect.Image) } if inspect_error { time.Sleep(time.Duration(*pImageCleanInterval+*pImageCleanDelayed) * time.Second) continue } } // Get all the locked image ID if *pImageLocked != "" { lockedImages := strings.Split(*pImageLocked, ",") for _, lockedImage := range lockedImages { imageInspect, err := client.InspectImage(strings.Trim(lockedImage, " ")) if err == nil { delete(imageIdMap, imageInspect.ID) } } } // Sleep for the delay time log.Printf("Img Cleanup: wait %d seconds for the cleaning", *pImageCleanDelayed) time.Sleep(time.Duration(*pImageCleanDelayed) * time.Second) // Get the image IDs used by all the containers again after the delay time containersDelayed, err := client.ListContainers(docker.ListContainersOptions{All: true}) if err != nil { log.Println("Img Cleanup: cannot get container list", err) time.Sleep(time.Duration(*pImageCleanInterval) * time.Second) continue } else { inspect_error := false for _, container := range containersDelayed { containerInspect, err := client.InspectContainer(container.ID) if err != nil { inspect_error = true log.Println("Img Cleanup: cannot get container inspect", err) break } delete(imageIdMap, containerInspect.Image) } if inspect_error { time.Sleep(time.Duration(*pImageCleanInterval) * time.Second) continue } } // Remove the unused images counter := 0 for id, removable := range imageIdMap { if removable { log.Printf("Img Cleanup: removing image %s", id) err := client.RemoveImage(id) if err != nil { log.Printf("Img Cleanup: %s", err) } counter += 1 } } log.Printf("Img Cleanup: %d images have been removed", counter) // Sleep again log.Printf("Img Cleanup: next cleanup will be start in %d seconds", *pImageCleanInterval) time.Sleep(time.Duration(*pImageCleanInterval) * time.Second) } }