func Init(docker *goDocker.Client, newContChan chan<- goDocker.Container, removeContChan chan<- string, drawStatsChan chan<- StatsMsg) { dockerEventChan = make(chan *goDocker.APIEvents, 10) statsResultsChan = make(chan StatsResult) statsResultsDoneChan = make(chan string) dockerClient = docker err := docker.AddEventListener(dockerEventChan) if err != nil { panic("Failed to add event listener: " + err.Error()) } go statsRenderingRoutine(drawStatsChan) go dockerEventRoutingRoutine(dockerEventChan, newContChan, removeContChan) containers, _ := dockerClient.ListContainers(goDocker.ListContainersOptions{}) Info.Println("Listing intial", len(containers), "containers as started") for _, cont := range containers { Info.Println("Marking", cont.ID, "as started") dockerEventChan <- &goDocker.APIEvents{ID: cont.ID, Status: "start"} //startedContainerChan <- cont.ID } }
// Action makes a skydns REST API call based on the docker event func Action(logger *log.Logger, action string, containerId string, docker *dockerapi.Client, TTL uint64, CONSUL string, DOMAIN string) { //if we fail on inspection, that is ok because we might //be checking for a crufty container that no longer exists //due to docker being shutdown uncleanly container, dockerErr := docker.InspectContainer(containerId) if dockerErr != nil { logger.Printf("unable to inspect container:%s %s", containerId, dockerErr) return } var hostname = container.Name[1:] var ipaddress = container.NetworkSettings.IPAddress if ipaddress == "" { logger.Println("no ipaddress returned for container: " + hostname) return } switch action { case "start": logger.Println("new container name=" + container.Name[1:] + " ip:" + ipaddress) Deregister(CONSUL, logger, hostname) service := Service{Name: hostname, Address: ipaddress} Register(CONSUL, logger, &service) case "stop": logger.Println("removing container name=" + container.Name[1:] + " ip:" + ipaddress) Deregister(CONSUL, logger, hostname) case "destroy": logger.Println("removing container name=" + container.Name[1:] + " ip:" + ipaddress) Deregister(CONSUL, logger, hostname) default: } }
func containerAddress(client *dockerapi.Client, containerId string) (string, error) { container, err := client.InspectContainer(containerId) if err != nil { return "", err } return container.NetworkSettings.IPAddress, nil }
// RegisterDockerEventListener registers function as event listener with docker. // laziness defines how many seconds to wait, after an event is received, until a refresh is triggered func RegisterDockerEventListener(client *docker.Client, function func(), wg *sync.WaitGroup, laziness int) { wg.Add(1) defer wg.Done() events := make(chan *docker.APIEvents) defer close(events) err := client.AddEventListener((chan<- *docker.APIEvents)(events)) if err != nil { log.Fatalf("Unable to add docker event listener: %s", err) } defer client.RemoveEventListener(events) log.Info("Listening to docker events...") for { event := <-events if event == nil { continue } if event.Status == "start" || event.Status == "stop" || event.Status == "die" { log.Debug("Received event %s for container %s", event.Status, event.ID[:12]) Refresh.Mu.Lock() if !Refresh.IsTriggered { log.Info("Triggering refresh in %d seconds", laziness) Refresh.timer = time.AfterFunc(time.Duration(laziness)*time.Second, function) Refresh.IsTriggered = true } Refresh.Mu.Unlock() } } }
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 Boot(client *docker.Client, opt *docker.CreateContainerOptions, exitCh chan error) (*docker.Container, error) { log.Debugf("Creating container for image %s", opt.Config.Image) container, err := client.CreateContainer(*opt) if err != nil { return container, err } log.Debugf("Starting container %s", container.ID) go func() { exitCh <- dockerpty.Start(client, container, opt.HostConfig) }() trial := 0 for { container, err = client.InspectContainer(container.ID) if container.State.StartedAt.Unix() > 0 { break } if trial > 30 { return container, fmt.Errorf("container %s seems not started. state=%#v", container.ID, container.State) } trial += 1 time.Sleep(time.Duration(trial*100) * time.Millisecond) } log.Debugf("container state=%#v", container.State) return container, nil }
// createImage creates a docker image either by pulling it from a registry or by // loading it from the file system func (d *DockerDriver) createImage(driverConfig *DockerDriverConfig, client *docker.Client, taskDir string) error { image := driverConfig.ImageName repo, tag := docker.ParseRepositoryTag(image) if tag == "" { tag = "latest" } var dockerImage *docker.Image var err error // 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 { if len(driverConfig.LoadImages) > 0 { return d.loadImage(driverConfig, client, taskDir) } return d.pullImage(driverConfig, client, repo, tag) } return err }
func execInContainer(client *docker.Client, id string, command []string) (string, string, error) { exec, err := client.CreateExec(docker.CreateExecOptions{ AttachStderr: true, AttachStdin: false, AttachStdout: true, Tty: false, Cmd: command, Container: id, }) if err != nil { return "", "", err } var outputBytes []byte outputWriter := bytes.NewBuffer(outputBytes) var errorBytes []byte errorWriter := bytes.NewBuffer(errorBytes) err = client.StartExec(exec.ID, docker.StartExecOptions{ OutputStream: outputWriter, ErrorStream: errorWriter, }) return outputWriter.String(), errorWriter.String(), err }
func destroyContainer(client *docker.Client, id string) error { return client.RemoveContainer(docker.RemoveContainerOptions{ ID: id, RemoveVolumes: true, Force: true, }) }
func fetchDockerContainer(name string, client *dc.Client) (*dc.APIContainers, error) { apiContainers, err := client.ListContainers(dc.ListContainersOptions{All: true}) if err != nil { return nil, fmt.Errorf("Error fetching container information from Docker: %s\n", err) } for _, apiContainer := range apiContainers { // Sometimes the Docker API prefixes container names with / // like it does in these commands. But if there's no // set name, it just uses the ID without a /...ugh. switch len(apiContainer.Names) { case 0: if apiContainer.ID == name { return &apiContainer, nil } default: for _, containerName := range apiContainer.Names { if strings.TrimLeft(containerName, "/") == name { return &apiContainer, nil } } } } return nil, nil }
func fetchDockerContainer(name string, client *dc.Client) (*dc.APIContainers, error) { apiContainers, err := client.ListContainers(dc.ListContainersOptions{All: true}) if err != nil { return nil, fmt.Errorf("Error fetching container information from Docker: %s\n", err) } for _, apiContainer := range apiContainers { // Sometimes the Docker API prefixes container names with / // like it does in these commands. But if there's no // set name, it just uses the ID without a /...ugh. var dockerContainerName string if len(apiContainer.Names) > 0 { dockerContainerName = strings.TrimLeft(apiContainer.Names[0], "/") } else { dockerContainerName = apiContainer.ID } if dockerContainerName == name { return &apiContainer, nil } } return nil, nil }
// build takes a Dockerfile and builds an image. func build(c cookoo.Context, path, tag string, client *docli.Client) error { dfile := filepath.Join(path, "Dockerfile") // Stat the file info, err := os.Stat(dfile) if err != nil { return fmt.Errorf("Dockerfile stat: %s", err) } file, err := os.Open(dfile) if err != nil { return fmt.Errorf("Dockerfile open: %s", err) } defer file.Close() var buf bytes.Buffer tw := tar.NewWriter(&buf) tw.WriteHeader(&tar.Header{ Name: "Dockerfile", Size: info.Size(), ModTime: info.ModTime(), }) io.Copy(tw, file) if err := tw.Close(); err != nil { return fmt.Errorf("Dockerfile tar: %s", err) } options := docli.BuildImageOptions{ Name: tag, InputStream: &buf, OutputStream: os.Stdout, } return client.BuildImage(options) }
func (cli *DogestryCli) getLayerIdsToDownload(fromId remote.ID, imageRoot string, r remote.Remote, client *docker.Client) ([]remote.ID, error) { toDownload := make([]remote.ID, 0) err := r.WalkImages(fromId, func(id remote.ID, image docker.Image, err error) error { fmt.Printf("Examining id '%s' on remote docker host...\n", id.Short()) if err != nil { return err } _, err = client.InspectImage(string(id)) if err == docker.ErrNoSuchImage { toDownload = append(toDownload, id) return nil } else if err != nil { return err } else { fmt.Printf("Docker host already has id '%s', stop scanning.\n", id.Short()) return remote.BreakWalk } return nil }) return toDownload, err }
// GetContainerNum returns container number in the system func GetContainerNum(client *docker.Client, all bool) int { containers, err := client.ListContainers(docker.ListContainersOptions{All: all}) if err != nil { panic(fmt.Sprintf("Error list containers: %v", err)) } return len(containers) }
// pullImage pulls the inspected image using the given client. // It will try to use all the given authentication methods and will fail // only if all of them failed. func (i *defaultImageInspector) pullImage(client *docker.Client) error { log.Printf("Pulling image %s", i.opts.Image) var imagePullAuths *docker.AuthConfigurations var authCfgErr error if imagePullAuths, authCfgErr = i.getAuthConfigs(); authCfgErr != nil { return authCfgErr } reader, writer := io.Pipe() // handle closing the reader/writer in the method that creates them defer writer.Close() defer reader.Close() imagePullOption := docker.PullImageOptions{ Repository: i.opts.Image, OutputStream: writer, RawJSONStream: true, } bytesChan := make(chan int) go aggregateBytesAndReport(bytesChan) go decodeDockerPullMessages(bytesChan, reader) // Try all the possible auth's from the config file var authErr error for name, auth := range imagePullAuths.Configs { if authErr = client.PullImage(imagePullOption, auth); authErr == nil { return nil } log.Printf("Authentication with %s failed: %v", name, authErr) } return fmt.Errorf("Unable to pull docker image: %v\n", authErr) }
func DoListContainerBenchmark(client *docker.Client, interval, testPeriod time.Duration, all bool, stopchan chan int) []int { startTime := time.Now() latencies := []int{} for { start := time.Now() client.ListContainers(docker.ListContainersOptions{All: all}) end := time.Now() latencies = append(latencies, int(end.Sub(start).Nanoseconds())) if stopchan == nil { if time.Now().Sub(startTime) >= testPeriod { return latencies } } else { select { case <-stopchan: return latencies default: } } if interval != 0 { time.Sleep(interval) } } return latencies }
func removeImage(d *schema.ResourceData, client *dc.Client) error { var data Data if keepLocally := d.Get("keep_locally").(bool); keepLocally { return nil } if err := fetchLocalImages(&data, client); err != nil { return err } imageName := d.Get("name").(string) if imageName == "" { return fmt.Errorf("Empty image name is not allowed") } foundImage := searchLocalImages(data, imageName) if foundImage != nil { err := client.RemoveImage(foundImage.ID) if err != nil { return err } } return nil }
func pullImage(client *dockerclient.Client, service *Service, image string) error { taglessRemote, tag := parsers.ParseRepositoryTag(image) if tag == "" { image = utils.ImageReference(taglessRemote, DefaultTag) } repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) if err != nil { return err } authConfig := cliconfig.AuthConfig{} if service.context.ConfigFile != nil && repoInfo != nil && repoInfo.Index != nil { authConfig = registry.ResolveAuthConfig(service.context.ConfigFile, repoInfo.Index) } err = client.PullImage( dockerclient.PullImageOptions{ Repository: image, OutputStream: os.Stderr, // TODO maybe get the stream from some configured place }, dockerclient.AuthConfiguration{ Username: authConfig.Username, Password: authConfig.Password, Email: authConfig.Email, }, ) if err != nil { logrus.Errorf("Failed to pull image %s: %v", image, err) } return err }
// cleanUp stops and removes the deployed router func cleanUp(dockerCli *dockerClient.Client, routerId string) { dockerCli.StopContainer(routerId, 5) dockerCli.RemoveContainer(dockerClient.RemoveContainerOptions{ ID: routerId, Force: true, }) }
func GetImageIDByImageName(client *docker.Client, image string) (string, error) { im, err := client.InspectImage(image) if err != nil { return "", err } return im.ID, nil }
// createGremlin creates the gremlin container using the docker client. // It is used only in the test code. func createGremlin(client *docker.Client) (*docker.Container, error) { container, err := client.CreateContainer(docker.CreateContainerOptions{ Config: &docker.Config{ Image: testImageName, }, }) return container, err }
func Tag(client *docker.Client, id, repo, tag string) (err error) { opts := docker.TagImageOptions{ Repo: repo, Tag: tag, } err = client.TagImage(id, opts) return }
func getContainers(client *docker.Client) []*docker.Container { allContainers, _ := client.ListContainers(docker.ListContainersOptions{All: false}) var containers []*docker.Container for _, c := range allContainers { container, _ := client.InspectContainer(c.ID) containers = append(containers, container) } return containers }
func SaveImage(client *docker.Client, image string, w io.Writer) (err error) { opts := docker.ExportImageOptions{ Name: image, OutputStream: w, } if err := client.ExportImage(opts); err != nil { return err } return nil }
// GetContainerIDs returns all the container ids in the system func GetContainerIDs(client *docker.Client) (containerIDs []string) { containers, err := client.ListContainers(docker.ListContainersOptions{All: true}) if err != nil { panic(fmt.Sprintf("Error list containers: %v", err)) } for _, container := range containers { containerIDs = append(containerIDs, container.ID) } return containerIDs }
func GetLayerIDs(client *docker.Client, name string) (ids []string, err error) { histories, err := client.ImageHistory(name) if err != nil { return } for _, history := range histories { ids = append(ids, history.ID) } return }
// RemoveContainers removes all the containers in ids slice func RemoveContainers(client *docker.Client, ids []string) { for _, id := range ids { removeOpts := docker.RemoveContainerOptions{ ID: id, } if err := client.RemoveContainer(removeOpts); err != nil { panic(fmt.Sprintf("Error remove containers: %v", err)) } } }
func runContainer(client *dockerapi.Client, createOpts dockerapi.CreateContainerOptions, startConfig *dockerapi.HostConfig) (string, error) { container, err := client.CreateContainer(createOpts) if err != nil { return "", err } err = client.StartContainer(container.ID, startConfig) // return container ID even if there is an error, so caller can clean up container if desired return container.ID, err }
func createContainer(client *docker.Client, opts docker.CreateContainerOptions) (c *container, err error) { var dockerInfo *docker.Container dockerInfo, err = client.CreateContainer(opts) if err == nil { c = &container{ client: client, id: dockerInfo.ID, } } return }
func getContainers(client *docker.Client) ([]*RuntimeContainer, error) { apiContainers, err := client.ListContainers(docker.ListContainersOptions{ All: false, Size: false, }) if err != nil { return nil, err } containers := []*RuntimeContainer{} for _, apiContainer := range apiContainers { container, err := client.InspectContainer(apiContainer.ID) if err != nil { log.Printf("error inspecting container: %s: %s\n", apiContainer.ID, err) continue } registry, repository, tag := splitDockerImage(container.Config.Image) runtimeContainer := &RuntimeContainer{ ID: container.ID, Image: DockerImage{ Registry: registry, Repository: repository, Tag: tag, }, Name: strings.TrimLeft(container.Name, "/"), Gateway: container.NetworkSettings.Gateway, Addresses: []Address{}, Env: make(map[string]string), } for k, v := range container.NetworkSettings.Ports { address := Address{ IP: container.NetworkSettings.IPAddress, Port: k.Port(), } if len(v) > 0 { address.HostPort = v[0].HostPort } runtimeContainer.Addresses = append(runtimeContainer.Addresses, address) } for _, entry := range container.Config.Env { parts := strings.Split(entry, "=") runtimeContainer.Env[parts[0]] = parts[1] } containers = append(containers, runtimeContainer) } return containers, nil }