Add image labels for base image, base image digest, and source#2163
Add image labels for base image, base image digest, and source#2163lbussell wants to merge 5 commits into
Conversation
| manifestServiceFactory: CreateManifestServiceFactoryMock( | ||
| localImageDigestResults: [new(baseImageTag, baseImageDigest)]).Object, | ||
| imageCacheService: new ImageCacheService(Mock.Of<ILogger<ImageCacheService>>(), Mock.Of<IGitService>())); | ||
| command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); |
| command.Options.SourceRepoUrl = sourceRepoUrl; | ||
|
|
||
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); |
|
|
||
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); | ||
| string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile"); |
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); | ||
| string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile"); | ||
| string dockerfileAbsolutePath = PathHelper.NormalizePath(Path.Combine(tempFolderContext.Path, dockerfileRelativePath)); |
| CreateImage( | ||
| new Platform[] { platform }))); | ||
|
|
||
| File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); |
| copyImageService: Mock.Of<ICopyImageService>(), | ||
| manifestServiceFactory: CreateManifestServiceFactoryMock().Object, | ||
| imageCacheService: new ImageCacheService(Mock.Of<ILogger<ImageCacheService>>(), Mock.Of<IGitService>())); | ||
| command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); |
| command.Options.Manifest = Path.Combine(tempFolderContext.Path, "manifest.json"); | ||
|
|
||
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); |
|
|
||
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); | ||
| string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile"); |
| const string runtimeRelativeDir = "1.0/runtime/os"; | ||
| Directory.CreateDirectory(Path.Combine(tempFolderContext.Path, runtimeRelativeDir)); | ||
| string dockerfileRelativePath = Path.Combine(runtimeRelativeDir, "Dockerfile"); | ||
| string dockerfileAbsolutePath = PathHelper.NormalizePath(Path.Combine(tempFolderContext.Path, dockerfileRelativePath)); |
| CreateImage( | ||
| new Platform[] { platform }))); | ||
|
|
||
| File.WriteAllText(Path.Combine(tempFolderContext.Path, command.Options.Manifest), JsonConvert.SerializeObject(manifest)); |
| IEnumerable<TagInfo> tagsForDigest = imageArtifactDetails is null ? [] : concreteTags; | ||
|
|
||
| // Log in again to refresh token as it may have expired from a long build | ||
| await ExecuteWithDockerCredentialsAsync( |
There was a problem hiding this comment.
What are the perf consequences of running this for every single image that gets built?
There was a problem hiding this comment.
I'm testing it internally and I'll get back to you.
| string? digest = null; | ||
| for (int attempt = 0; attempt <= RetryHelper.MaxRetries && digest is null; attempt++) | ||
| { | ||
| digest = await imageDigestCache.GetLocalImageDigestAsync(tag.FullyQualifiedName, Options.IsDryRun); |
There was a problem hiding this comment.
Include some sort of timing backoff for each attempt.
There was a problem hiding this comment.
I'm going to take a second pass at this method. This is not how we should do retries. Thanks for calling it out.
| string repoRoot = _gitService.GetRepoRoot(platform.DockerfilePath); | ||
| labels[ImageBuilderLabels.Dockerfile] = | ||
| PathHelper.NormalizePath(Path.GetRelativePath(repoRoot, platform.DockerfilePath)); |
There was a problem hiding this comment.
Use GitServiceExtensions.GetDockerfileCommitUrl instead?
There was a problem hiding this comment.
This is a workaround for #2165. Additionally, since the source URL is already present in the org.opencontainers.image.source label, including the repo base URL a second time in another label is not necessary. That's why I chose only the Dockerfile path here.
There was a problem hiding this comment.
If we already have org.opencontainers.image.source then why do we need this label?
Part of #1602.
This PR adds the following labels to images automatically at build time.
org.opencontainers.image.sourcehttps://github.com/dotnet/docker-toolsorg.opencontainers.image.revisionc0ffeec0ffeec0ffee...org.opencontainers.image.base.namemcr.microsoft.com/dotnet/runtime:9.0-azurelinux3.0org.opencontainers.image.base.digestsha256:abcdef123456...com.microsoft.imagebuilder.dockerfilesrc/Dockerfile.linuxI needed to add one custom label,
com.microsoft.imagebuilder.dockerfile, in order to maintain parity with what's tracked in ImageArtifactDetails/image-info.json. It contains the path to the Dockerfile that the image was built from relative to the repo root.Change to the build command's execution flow
While the git diff doesn't show it nicely, this PR rearranges the steps in the build command. Previously, there were multiple loops over all images. Now, everything is computed in one loop. This is necessary in order for downstream/intermediate images to have accurate base image digest labels set at build time. Here is a high-level before/after comparison:
Before:
After:
Note: labels are inherited by downstream images by default.