Skip to content

Allow users to set a specific ContainerImageFormat to force OCI support #46011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -34,6 +40,7 @@ internal static async Task<int> ContainerizeAsync(
string? archiveOutputPath,
bool generateLabels,
bool generateDigestLabel,
KnownImageFormats? imageFormat,
ILoggerFactory loggerFactory,
CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -99,6 +106,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 @@ -19,7 +19,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 @@ -32,15 +31,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 @@ -70,14 +69,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 @@ -243,6 +243,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.get -> b
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.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 @@ -90,6 +90,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.get -> b
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GenerateDigestLabel.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 @@ -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
Loading