Skip to content

Commit

Permalink
[release/8.0.4xx] Manual Backport of #40611 to 8.0.4xx - Allow users …
Browse files Browse the repository at this point in the history
…to set a specific ContainerImageFormat to force OCI support (#46140)
  • Loading branch information
baronfel authored Feb 11, 2025
1 parent ca5f4da commit bca34b9
Show file tree
Hide file tree
Showing 26 changed files with 313 additions and 96 deletions.
16 changes: 16 additions & 0 deletions src/Containers/Microsoft.NET.Build.Containers/ContainerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

namespace Microsoft.NET.Build.Containers;

internal enum KnownImageFormats
{
OCI,
Docker
}

internal static class ContainerBuilder
{
internal static async Task<int> ContainerizeAsync(
Expand Down Expand Up @@ -33,6 +39,7 @@ internal static async Task<int> ContainerizeAsync(
string? archiveOutputPath,
bool generateLabels,
bool generateDigestLabel,
KnownImageFormats? imageFormat,
ILoggerFactory loggerFactory,
CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -98,6 +105,15 @@ internal static async Task<int> ContainerizeAsync(
logger.LogInformation(Strings.ContainerBuilder_StartBuildingImage, imageName, string.Join(",", imageName), sourceImageReference);
cancellationToken.ThrowIfCancellationRequested();

// forcibly change the media type if required
imageBuilder.ManifestMediaType = imageFormat switch
{
null => imageBuilder.ManifestMediaType,
KnownImageFormats.Docker => SchemaTypes.DockerManifestV2,
KnownImageFormats.OCI => SchemaTypes.OciManifestV1,
_ => imageBuilder.ManifestMediaType // should be impossible unless we add to the enum
};

Layer newLayer = Layer.FromDirectory(publishDirectory.FullName, workingDir, imageBuilder.IsWindows, imageBuilder.ManifestMediaType);
imageBuilder.AddLayer(newLayer);
imageBuilder.SetWorkingDirectory(workingDir);
Expand Down
17 changes: 11 additions & 6 deletions src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ internal sealed class ImageBuilder

// the mutable internal manifest that we're building by modifying the base and applying customizations
private readonly ManifestV2 _manifest;
private readonly string _manifestMediaType;
private readonly ImageConfig _baseImageConfig;
private readonly ILogger _logger;

Expand All @@ -33,15 +32,15 @@ internal sealed class ImageBuilder
public ImageConfig BaseImageConfig => _baseImageConfig;

/// <summary>
/// MediaType of the output manifest.
/// MediaType of the output manifest. By default, this will be the same as the base image manifest.
/// </summary>
public string ManifestMediaType => _manifestMediaType; // output the same media type as the base image manifest.
public string ManifestMediaType { get; set; }

internal ImageBuilder(ManifestV2 manifest, string manifestMediaType, ImageConfig baseImageConfig, ILogger logger)
{
_baseImageManifest = manifest;
_manifest = new ManifestV2() { SchemaVersion = manifest.SchemaVersion, Config = manifest.Config, Layers = new(manifest.Layers), MediaType = manifest.MediaType };
_manifestMediaType = manifestMediaType;
ManifestMediaType = manifestMediaType;
_baseImageConfig = baseImageConfig;
_logger = logger;
}
Expand Down Expand Up @@ -71,14 +70,20 @@ internal BuiltImage Build()
ManifestConfig newManifestConfig = _manifest.Config with
{
digest = imageDigest,
size = imageSize
size = imageSize,
mediaType = ManifestMediaType switch
{
SchemaTypes.OciManifestV1 => SchemaTypes.OciImageConfigV1,
SchemaTypes.DockerManifestV2 => SchemaTypes.DockerContainerV1,
_ => SchemaTypes.OciImageConfigV1 // opinion - defaulting to modern here, but really this should never happen
}
};

ManifestV2 newManifest = new ManifestV2()
{
Config = newManifestConfig,
SchemaVersion = _manifest.SchemaVersion,
MediaType = _manifest.MediaType,
MediaType = ManifestMediaType,
Layers = _manifest.Layers
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.SkipPublishing.get -> bool
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.SkipPublishing.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.get -> string?
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.set -> void
override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ToolName.get -> string!
override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateCommandLineCommands() -> string!
override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateFullPathToTool() -> string!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.SkipPublishing.get -> bool
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.SkipPublishing.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerNames.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.get -> string?
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageFormat.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.set -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ internal class SchemaTypes
internal const string DockerContainerV1 = "application/vnd.docker.container.image.v1+json";
internal const string DockerManifestListV2 = "application/vnd.docker.distribution.manifest.list.v2+json";
internal const string DockerManifestV2 = "application/vnd.docker.distribution.manifest.v2+json";

internal const string OciManifestV1 = "application/vnd.oci.image.manifest.v1+json"; // https://containers.gitbook.io/build-containers-the-hard-way/#registry-format-oci-image-manifest
internal const string OciImageIndexV1 = "application/vnd.oci.image.index.v1+json";
internal const string OciImageConfigV1 = "application/vnd.oci.image.config.v1+json";

internal const string DockerLayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip";
internal const string OciLayerGzipV1 = "application/vnd.oci.image.layer.v1.tar+gzip";
}
Loading

0 comments on commit bca34b9

Please sign in to comment.