in container/docker/handler.go [113:249]
func newDockerContainerHandler(
client *docker.Client,
name string,
machineInfoFactory info.MachineInfoFactory,
fsInfo fs.FsInfo,
storageDriver StorageDriver,
storageDir string,
cgroupSubsystems map[string]string,
inHostNamespace bool,
metadataEnvAllowList []string,
dockerVersion []int,
includedMetrics container.MetricSet,
thinPoolName string,
thinPoolWatcher *devicemapper.ThinPoolWatcher,
zfsWatcher *zfs.ZfsWatcher,
) (container.ContainerHandler, error) {
// Create the cgroup paths.
cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems, name)
// Generate the equivalent cgroup manager for this container.
cgroupManager, err := containerlibcontainer.NewCgroupManager(name, cgroupPaths)
if err != nil {
return nil, err
}
rootFs := "/"
if !inHostNamespace {
rootFs = "/rootfs"
storageDir = path.Join(rootFs, storageDir)
}
id := dockerutil.ContainerNameToId(name)
// Add the Containers dir where the log files are stored.
// FIXME: Give `otherStorageDir` a more descriptive name.
otherStorageDir := path.Join(storageDir, pathToContainersDir, id)
rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion)
if err != nil {
return nil, err
}
// Determine the rootfs storage dir OR the pool name to determine the device.
// For devicemapper, we only need the thin pool name, and that is passed in to this call
rootfsStorageDir, zfsFilesystem, zfsParent, err := DetermineDeviceStorage(storageDriver, storageDir, rwLayerID)
if err != nil {
return nil, fmt.Errorf("unable to determine device storage: %v", err)
}
// We assume that if Inspect fails then the container is not known to docker.
ctnr, err := client.ContainerInspect(context.Background(), id)
if err != nil {
return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
}
// Do not report network metrics for containers that share netns with another container.
metrics := common.RemoveNetMetrics(includedMetrics, ctnr.HostConfig.NetworkMode.IsContainer())
// TODO: extract object mother method
handler := &dockerContainerHandler{
machineInfoFactory: machineInfoFactory,
cgroupPaths: cgroupPaths,
fsInfo: fsInfo,
storageDriver: storageDriver,
poolName: thinPoolName,
rootfsStorageDir: rootfsStorageDir,
envs: make(map[string]string),
labels: ctnr.Config.Labels,
includedMetrics: metrics,
zfsParent: zfsParent,
}
// Timestamp returned by Docker is in time.RFC3339Nano format.
handler.creationTime, err = time.Parse(time.RFC3339Nano, ctnr.Created)
if err != nil {
// This should not happen, report the error just in case
return nil, fmt.Errorf("failed to parse the create timestamp %q for container %q: %v", ctnr.Created, id, err)
}
handler.libcontainerHandler = containerlibcontainer.NewHandler(cgroupManager, rootFs, ctnr.State.Pid, metrics)
// Add the name and bare ID as aliases of the container.
handler.reference = info.ContainerReference{
Id: id,
Name: name,
Aliases: []string{strings.TrimPrefix(ctnr.Name, "/"), id},
Namespace: DockerNamespace,
}
handler.image = ctnr.Config.Image
// Only adds restartcount label if it's greater than 0
if ctnr.RestartCount > 0 {
handler.labels["restartcount"] = strconv.Itoa(ctnr.RestartCount)
}
// Obtain the IP address for the container.
// If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified.
// This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address
ipAddress := ctnr.NetworkSettings.IPAddress
networkMode := string(ctnr.HostConfig.NetworkMode)
if ipAddress == "" && strings.HasPrefix(networkMode, "container:") {
containerID := strings.TrimPrefix(networkMode, "container:")
c, err := client.ContainerInspect(context.Background(), containerID)
if err != nil {
return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
}
ipAddress = c.NetworkSettings.IPAddress
}
handler.ipAddress = ipAddress
if includedMetrics.Has(container.DiskUsageMetrics) {
handler.fsHandler = &FsHandler{
FsHandler: common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, otherStorageDir, fsInfo),
ThinPoolWatcher: thinPoolWatcher,
ZfsWatcher: zfsWatcher,
DeviceID: ctnr.GraphDriver.Data["DeviceId"],
ZfsFilesystem: zfsFilesystem,
}
}
// split env vars to get metadata map.
for _, exposedEnv := range metadataEnvAllowList {
if exposedEnv == "" {
// if no dockerEnvWhitelist provided, len(metadataEnvAllowList) == 1, metadataEnvAllowList[0] == ""
continue
}
for _, envVar := range ctnr.Config.Env {
if envVar != "" {
splits := strings.SplitN(envVar, "=", 2)
if len(splits) == 2 && strings.HasPrefix(splits[0], exposedEnv) {
handler.envs[strings.ToLower(splits[0])] = splits[1]
}
}
}
}
return handler, nil
}