Example #1
0
        private void _insertNodeIntoLeafsQueue(IList <DockerImageNode> leafs, DockerImageNode node)
        {
            var index = leafs.Count;

            for (int i = 0; i < leafs.Count; i++)
            {
                if (ImageDeletionOrder is ImageDeletionOrderType.ByImageCreationDate)
                {
                    if (node.InspectResponse.Created < leafs[i].InspectResponse.Created)
                    {
                        index = i;
                        break;
                    }
                }
                else if (ImageDeletionOrder is ImageDeletionOrderType.ByImageLastTouchDate)
                {
                    if (node.GetImageLastTouchDate(this._imageLastTouchDate) < leafs[i].GetImageLastTouchDate(this._imageLastTouchDate))
                    {
                        index = i;
                        break;
                    }
                }
            }
            leafs.Insert(index, node);
        }
Example #2
0
        private void DeleteImage(DockerImageNode image, string repoTag)
        {
            var imageShortId = DockerImageNode.GetImageShortId(image.InspectResponse.ID);
            var imageRepoTag = repoTag ?? "<none>";

            Console.WriteLine($"[{DateTime.UtcNow.ToString()} UTC] Preparing to delete image: {imageShortId} ({imageRepoTag})");

            // Delete image
            if (!string.IsNullOrEmpty(repoTag))
            {
                _dockerClient.Images.DeleteImageAsync($"{imageRepoTag}", new ImageDeleteParameters()
                {
                    Force = false, PruneChildren = true
                }).Wait();
            }
            else
            {
                _dockerClient.Images.DeleteImageAsync(image.InspectResponse.ID, new ImageDeleteParameters()
                {
                    Force = false, PruneChildren = true
                }).Wait();
            }

            Console.WriteLine($"[{DateTime.UtcNow.ToString()} UTC] Image deleted: {imageShortId} ({imageRepoTag})");
        }
Example #3
0
        // Build image dependency tree
        public DockerImageNode BuildImageTree(IList <ImageInspectResponse> images,
                                              IList <ContainerListResponse> containerListResponses,
                                              IList <ContainerInspectResponse> containerInspectResponses,
                                              ImageInspectResponse image)
        {
            var containerList = containerListResponses.Where(r => string.Equals(r.ImageID, image.ID)).ToList();
            IList <ContainerInspectResponse> containers = new List <ContainerInspectResponse>();

            foreach (var container in containerList)
            {
                containers.Add(containerInspectResponses.Where(c => string.Equals(c.ID, container.ID)).FirstOrDefault());
            }

            var dockerImageNode = new DockerImageNode()
            {
                InspectResponse = image,
                Children        = new List <DockerImageNode>(),
                Containers      = containers,
            };

            var children = images.Where(i => string.Equals(i.Parent, image.ID)).ToList();

            foreach (var child in children)
            {
                var childNode = BuildImageTree(images, containerListResponses, containerInspectResponses, child);
                childNode.Parent = dockerImageNode;
                dockerImageNode.Children.Add(childNode);
            }

            return(dockerImageNode);
        }
Example #4
0
        private long _getTotalDiskSpaceUsage(DockerImageNode imageNode)
        {
            var diskUsage = imageNode.DiskSize;

            foreach (var child in imageNode.Children)
            {
                diskUsage += _getTotalDiskSpaceUsage(child);
            }

            return(diskUsage);
        }
Example #5
0
        private IList <DockerImageNode> _getParents(DockerImageNode imageNode)
        {
            var node    = imageNode;
            var parents = new List <DockerImageNode>();

            while (node.Parent != null)
            {
                node = node.Parent;
                parents.Add(node);
            }

            return(parents);
        }
Example #6
0
        public bool CanDelete(DockerImageNode imageNode)
        {
            // We DO NOT delete image if it is in the whitelist
            if (this._imageWhitelist.MatchAny(imageNode.InspectResponse.RepoTags))
            {
                return(false);
            }

            // We DO NOT delete image if there is a non blacklist state container exists using that image
            if (imageNode.GetContainerCount() - imageNode.GetContainerCount(_stateBlacklist) > 0)
            {
                return(false);
            }

            return(true);
        }
Example #7
0
        private IList <DockerImageNode> _getLeafImageNodes(DockerImageNode imageNode)
        {
            if (imageNode.Children.Count == 0)
            {
                return(new List <DockerImageNode> {
                    imageNode
                });
            }

            var leafs = new List <DockerImageNode>();

            foreach (var child in imageNode.Children)
            {
                leafs.AddRange(_getLeafImageNodes(child));
            }

            return(leafs);
        }
Example #8
0
        private void DeleteImages(IList <DockerImageNode> images)
        {
            var recycledDiskSize = 0L;
            var deletedImages    = 0;

            var dic = new Dictionary <string, int>();

            foreach (var image in images)
            {
                var imageShortId  = DockerImageNode.GetImageShortId(image.InspectResponse.ID);
                var imageRepoTags = image.InspectResponse.RepoTags;

                try
                {
                    // Remove containers in black list states
                    StopAndRemoveContainers(image);

                    // Delete tagged image references
                    foreach (var repoTag in imageRepoTags)
                    {
                        DeleteImage(image, repoTag);
                    }

                    // Delete untagged image
                    if (imageRepoTags.Count() == 0)
                    {
                        DeleteImage(image, null);
                    }

                    recycledDiskSize += image.DiskSize;
                    deletedImages++;
                }
                // If container created before we delete the image, docker will throw exception
                // In this case, we catch the exception here but keep on deleting
                catch (Exception e)
                {
                    Console.Error.WriteLine($"[{DateTime.UtcNow.ToString()} UTC] {e}");
                }
            }

            Console.WriteLine($"[{DateTime.UtcNow.ToString()} UTC] {deletedImages} images deleted (total of {(int)(recycledDiskSize / (1024 * 1024))} MB)");
            _logger.LogCounter("images-recycled-count", deletedImages);
            _logger.LogCounter("disk-space-recycled-mb", (int)(recycledDiskSize / (1024 * 1024)));
        }
        private void _printDependencyGraph(DockerImageNode node, IList <DockerImageNode> highlights, IMatchlist containerStateBlacklist, int indentOffset = 0, int indent = 2, string highlightMarker = "<---")
        {
            Console.Write(_indent(indentOffset) + $"Image: {DockerImageNode.GetImageShortId(node.InspectResponse.ID)} ({node.InspectResponse.RepoTags.FirstOrDefault() ?? "<none>"}) {(int)((DateTime.UtcNow - node.InspectResponse.Created).TotalDays)} days {node.DiskSize/(1024*1024)} MB ");

            if (node.Containers.Count > 0)
            {
                Console.Write($"({node.GetContainerCount() - node.GetContainerCount(containerStateBlacklist)}/{node.Containers.Count}) ");
            }

            if (highlights.Any(i => string.Equals(i.InspectResponse.ID, node.InspectResponse.ID, StringComparison.InvariantCultureIgnoreCase)))
            {
                Console.Write($"{highlightMarker} {highlights.IndexOf(node) + 1}");
            }

            Console.WriteLine();

            foreach (var child in node.Children)
            {
                _printDependencyGraph(child, highlights, containerStateBlacklist, indentOffset + indent);
            }
        }
Example #10
0
        // Returns true when all child images can be deleted, meaning all child images have no running containers (all dead or exited)
        // and they are old enough to be safely deleted.
        private bool _canDelete(DockerImageNode image, List <DockerImageNode> imagesToBeRecycledInOrder)
        {
            var canDelete = true;

            foreach (var child in image.Children)
            {
                if (!_canDelete(child, imagesToBeRecycledInOrder))
                {
                    canDelete = false;
                }
                else
                {
                    imagesToBeRecycledInOrder.Add(child);
                }
            }

            if (ImageDeletionOrder is ImageDeletionOrderType.ByImageCreationDate)
            {
                if (image.InspectResponse.Created >= DateTime.UtcNow.AddDays(-this.DaysBeforeDeletion))
                {
                    return(false);
                }
            }
            else if (ImageDeletionOrder is ImageDeletionOrderType.ByImageLastTouchDate)
            {
                var imageLastTouchDate = image.GetImageLastTouchDate(this._imageLastTouchDate);

                if (imageLastTouchDate >= DateTime.UtcNow.AddDays(-this.DaysBeforeDeletion))
                {
                    return(false);
                }
            }

            if (!base.CanDelete(image))
            {
                canDelete = false;
            }

            return(canDelete);
        }
Example #11
0
        private void StopAndRemoveContainers(DockerImageNode image)
        {
            var imageShortId = DockerImageNode.GetImageShortId(image.InspectResponse.ID);

            // Remove containers in black list states
            foreach (var container in image.Containers)
            {
                var status = _dockerClient.Containers.InspectContainerAsync(container.ID).Result.State.Status;
                // If container state changed and not in black list states, we should skip deleting
                if (!_containerStateBlacklist.Match(status))
                {
                    throw new Exception($"Postponed deletion for image: {imageShortId} due to container status change");
                }
                else
                {
                    Console.WriteLine($"[{DateTime.UtcNow.ToString()} UTC] Stop and remove container: {container.ID} using image: {imageShortId}");
                    _dockerClient.Containers.StopContainerAsync(container.ID, new ContainerStopParameters()).Wait();
                    _dockerClient.Containers.RemoveContainerAsync(container.ID, new ContainerRemoveParameters()
                    {
                        Force = false, RemoveLinks = false, RemoveVolumes = false
                    }).Wait();
                }
            }
        }
 public long GetDiskspaceUsage(DockerImageNode image)
 {
     return(image.DiskSize + image.Children.Sum(i => GetDiskspaceUsage(i)));
 }