dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.07k forks source link

ParseContainerProperties task normalizes the registry part of the repository #44408

Open paulomorgado opened 2 weeks ago

paulomorgado commented 2 weeks ago

I'm specifying my container repository as:

<ContainerRepository>myregistry.com:123/$(AssemblyName)</ContainerRepository>

But the ParseContainerProperties task "normalizes" it to "myregistry-com-123/...."

the only way for it to work, is to use this:

<ContainerRepository>myregistry.com:123/$(AssemblyName.Replace('.','-').ToLowerInvariant())</ContainerRepository>

Is that intended?

What is the ContainerRegistry parameter used for?

baronfel commented 2 weeks ago

In container terminology, the repository is the Image Name - including any slashes or namespacing via paths. It has certain normalization rules that must be followed by spec.

The Registry is the remote resource that stores the generated container.

So in your case you need to set ContainerRegistry to 'myregistry.com:123' and remove that portion from ContainerRepository.

You can find detailed docs for all of these properties at our repo.

paulomorgado commented 2 weeks ago

What is the ContainerRegistry used for, them?

What do I have to do to produce an image with the repository in its fully qualified name?

baronfel commented 2 weeks ago

ContainerRegistry is used to tell the system to push the image to a given registry. To push your current example to the remote registry you should use:

<PropertyGroup>
  <ContainerRegistry>myregistry.com:123</ContainerRegistry>
</PropertyGroup>

The tooling will interpret this as "push the $(ContainerRegistry)/$(Assembly):latest container to the $(ContainerRegistry) registry".

There is no tooling available right now for the Docker-style process of "build an image locally with a fully-qualified name, and then later push that that fully-qualified image to a remote registry".

paulomorgado commented 2 weeks ago

What tooling?

I'm generating an image archive with path set by ContainerArchiveOutputPath.

Other tooling will load the image archive into a local docker engine and docker cli or Docker.DotNet will be used to push the image.

Maybe there should be a property to indicate that the image should include the registry.

baronfel commented 2 weeks ago

Can you provide a sample or set of commands and describe what your end to end is, and what specifically is failing for you? I'm having a hard time seeing what the desired state is for your scenario.

paulomorgado commented 2 weeks ago
  1. Use .NET SDK to produce an archive of the container image.
  2. Load the container image: docker load --input <path to the image archive file>
  3. Push the desired image tags to the registry: docker push <name>:<tag>

The infrastructure doing the push, has no information other than the archive file and a list of approved tag patterns.

baronfel commented 2 weeks ago

Ok, this is related to the way we think about constructing the images in the SDK container tooling. In Docker tooling the name of the image and its storage are distinct - you can have a local image called localhost:12345/blah:foo and that will work just fine. Docker then allows you to push that named image to its backing remote registry.

Our tooling doesn't have that same understanding. The Repository is the thing that's stable, but the presence or absence of the ContainerRegistry influences both the name of the image reference to be created as well as its destination. We would need to make the archive publishing aware of ContainerRegistry, but that might have other impacts based on how coupled the two concepts are in our tooling.

paulomorgado commented 2 weeks ago

Maybe a ContainerFullyQualifiedImageName property would work.

If supplied, it would ignore ContainerRegistry and ContainerRepository and use it instead.

paulomorgado commented 2 weeks ago

@baronfel,

my.registry.com:123/my-repository is considered valid and not normalized.

However, my.registry.com:123/my.repository is normalized to my-registry-com-123/my-repository.

I don't think this is consistent or expected behavior.

paulomorgado commented 1 week ago

@baronfel,

Trying to debug this, I found out that my.repository.name is not normalized, but My.Repository.Name is normalized into my-repository-name.

containerRepository normalizedImageName normalizationWarning normalizationError
My-Repository-Name my-repository-name NormalizedContainerName
My.Repository.Name my-repository-name NormalizedContainerName
my.repository.name my.repository.name

Is this the intended result?

If so, why?

According to https://docs.docker.com/docker-hub/repos/create/, upper case letters should be allowed and .s should not be allowed.