Example #1
0
// CheckPrereqs will ensure that there are not multiple instances of the
// watchtower running simultaneously. If multiple watchtower containers are
// detected, this function will stop and remove all but the most recently
// started container.
func CheckPrereqs(client container.Client, cleanup bool) error {
	containers, err := client.ListContainers(watchtowerContainersFilter)
	if err != nil {
		return err
	}

	if len(containers) > 1 {
		sort.Sort(container.ByCreated(containers))

		// Iterate over all containers execept the last one
		for _, c := range containers[0 : len(containers)-1] {
			client.StopContainer(c, 60)

			if cleanup {
				client.RemoveImage(c)
			}
		}
	}

	return nil
}
Example #2
0
// Update looks at the running Docker containers to see if any of the images
// used to start those containers have been updated. If a change is detected in
// any of the images, the associated containers are stopped and restarted with
// the new image.
func Update(client container.Client, names []string, cleanup bool) error {
	log.Info("Checking containers for updated images")

	containers, err := client.ListContainers(containerFilter(names))
	if err != nil {
		return err
	}

	for i, container := range containers {
		stale, err := client.IsContainerStale(container)
		if err != nil {
			return err
		}
		containers[i].Stale = stale
	}

	containers, err = container.SortByDependencies(containers)
	if err != nil {
		return err
	}

	checkDependencies(containers)

	// Stop stale containers in reverse order
	for i := len(containers) - 1; i >= 0; i-- {
		container := containers[i]

		if container.IsWatchtower() {
			continue
		}

		if container.Stale {
			if err := client.StopContainer(container, waitTime); err != nil {
				log.Error(err)
			}
		}
	}

	// Restart stale containers in sorted order
	for _, container := range containers {
		if container.Stale {
			// Since we can't shutdown a watchtower container immediately, we need to
			// start the new one while the old one is still running. This prevents us
			// from re-using the same container name so we first rename the current
			// instance so that the new one can adopt the old name.
			if container.IsWatchtower() {
				if err := client.RenameContainer(container, randName()); err != nil {
					log.Error(err)
					continue
				}
			}

			if err := client.StartContainer(container); err != nil {
				log.Error(err)
			}

			if cleanup {
				client.RemoveImage(container)
			}
		}
	}

	return nil
}