Skip to content

Conversation

JonathanMbt
Copy link
Contributor

Allow to share an image from a private registry and not only docker.io

Would allow to share for instance an image tagged like this:

my.private-registry.com:5000/random/hello-world:1.0

@JonathanMbt JonathanMbt changed the title Add support for private registries feat: Add support for private registries Jul 1, 2025
@tonyo
Copy link
Collaborator

tonyo commented Jul 10, 2025

What exact error are you getting now?

Non-docker.io registries should work, e.g. this does for me:

docker pussh ghcr.io/psviderski/unregistry root@XXXX

@JonathanMbt
Copy link
Contributor Author

JonathanMbt commented Jul 10, 2025

Ok sorry my bad I haven't tested it to the end. I now have the cause of the failure, if you have a private registry with a port different of 443 the image is not considered valid.

Steps to reproduce:

 docker tag ghcr.io/psviderski/unregistry private.registry.com:8000/psviderski/unregistry
 docker pussh private.registry.com:8000/psviderski/unregistry root@XXXX
 
 • Connecting to root...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:55455 on remote host.
 ✓ Forwarded localhost:55314 to unregistry over SSH connection.
Error parsing reference: "localhost:55314/private.registry.com:8000/psviderski/unregistry" is not a valid repository/tag: invalid reference format
 ! Cleaning up after error...

So more precisely, the change that I've made is to support the official docker image name format https://docs.docker.com/reference/cli/docker/image/tag/ which is the following:

[HOST[:PORT]/]NAMESPACE/REPOSITORY[:TAG]

It does not work because:

HOST: localhost
PORT: 55314
NAMESPACE: private.registry.com:8000 (not valid)
REPOSITORY: psviderski/unregistry

But it should be working because the image format is correct:

HOST: private.registry.com
PORT: 8000
NAMESPACE: psviderski
REPOSITORY: unregistry

But as we are already using a registry (the unregistry), host and port info is already specified...
On the other end it does work when the port of the registry is 443 as default one and as such is not specified:

HOST: localhost
PORT: 55314
NAMESPACE: ghcr.io (valid, but ghcr.io:443 not valid)
REPOSITORY: psviderski/unregistry

In order to do that I quit the host, port and namespace part of the image, push it and then tag it by re-adding the host,port and namespace part (while remove the image without the info).

Copy link
Collaborator

@tonyo tonyo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right; thanks for the fix.
Left a few suggestions.

Please rebase on top of the latest master, it should add some CI checks for the code.

@JonathanMbt
Copy link
Contributor Author

I've made the changes suggested, and squashed the 2 commits as well as the rebase.

@tonyo
Copy link
Collaborator

tonyo commented Jul 17, 2025

Ran a test, there is a minor thing that I'd like to get fixed (update the name of the temporary image so it doesn't potentially collide with existing images), but let me do this as a follow-up.
Good stuff, thanks for the fix 👍

@tonyo tonyo merged commit 7b59d9f into psviderski:main Jul 17, 2025
1 check failed
@psviderski
Copy link
Owner

I didn't investigate but image parsing logic doesn't work for me (bash, version 5.2.37(1)-release (aarch64-apple-darwin23.6.0))

docker pussh debian [email protected]
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:64404 on remote host.
 ✓ Forwarded localhost:57825 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:57825...
 ✓ Additional tunnel created: localhost:60240 → localhost:57825
ERROR: Error parsing reference: debian is not a valid image reference.
 ! Cleaning up after error...

docker pussh alpine/socat [email protected]                                                                                                                              1426ms
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:57420 on remote host.
 ✓ Forwarded localhost:56214 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:56214...
 ✓ Additional tunnel created: localhost:60956 → localhost:56214
ERROR: Error parsing reference: alpine/socat is not a valid image reference.
 ! Cleaning up after error...

docker pussh ghcr.io/psviderski/ucind [email protected]                                                                                                                  1679ms
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:63853 on remote host.
 ✓ Forwarded localhost:60635 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:60635...
 ✓ Additional tunnel created: localhost:55823 → localhost:60635
ERROR: Error parsing reference: ghcr.io/psviderski/ucind is not a valid image reference.
 ! Cleaning up after error...

@psviderski
Copy link
Owner

psviderski commented Jul 18, 2025

My 2 cents regarding this change and @tonyo's follow-up: da2720e#diff-d5e4d037c1ed36953841f496931701101aaac3efc12860de17810a6e931fad81R417

Note that when Docker does not use the containerd image store, overtime it will be filled up with XXXX-image-without-registry-prefix or just image-without-registry-prefix (before @tonyo's follow-up) images. Not sure if this is a problem but I guess it introduces some discrepancy and makes it harder to automate the cleanup commands: https://github.com/psviderski/unregistry?tab=readme-ov-file#without-containerd-image-store-default-docker-behaviour

If we don't prefix with XXXX, there is a risk to override another image that has image-without-registry-prefix name.

Ideally, we'd want to retag the image in the containerd image store as well but we can't guarantee that the remote user has permissions to talk to containerd directly.

What else can we do?

  1. Do not support images with registry HOST that contains chars which are not allowed in NAMESPACE, e.g. colons : used to separate a port. But we can provide a clear error message in this case suggesting to manually retag the image before pusshing.
  2. Replace the invalid registry names with something deterministic that could be used as NAMESPACE, e.g.
    a. private.registry.com:8000 -> private.registry.com-8000 (it will stay as private.registry.com-8000 in the containerd store, if not used by Docker, but at least it's pretty straightforward for the user how the name was produced)
    b. private.registry.com:8000 -> private.registry.com YOLO? 😄
    c. private.registry.com:8000 -> 742906a (short hash which is IMO very unintuitive)
    d. ?

To me, 2a looks like a reasonable compromise. What do you guys think? @JonathanMbt, @tonyo

@JonathanMbt
Copy link
Contributor Author

I didn't investigate but image parsing logic doesn't work for me (bash, version 5.2.37(1)-release (aarch64-apple-darwin23.6.0))

docker pussh debian [email protected]
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:64404 on remote host.
 ✓ Forwarded localhost:57825 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:57825...
 ✓ Additional tunnel created: localhost:60240 → localhost:57825
ERROR: Error parsing reference: debian is not a valid image reference.
 ! Cleaning up after error...

docker pussh alpine/socat [email protected]                                                                                                                              1426ms
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:57420 on remote host.
 ✓ Forwarded localhost:56214 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:56214...
 ✓ Additional tunnel created: localhost:60956 → localhost:56214
ERROR: Error parsing reference: alpine/socat is not a valid image reference.
 ! Cleaning up after error...

docker pussh ghcr.io/psviderski/ucind [email protected]                                                                                                                  1679ms
 • Connecting to [email protected]...
 • Starting unregistry container on remote host...
 ✓ Unregistry is listening localhost:63853 on remote host.
 ✓ Forwarded localhost:60635 to unregistry over SSH connection.
 • Detected virtualized Docker, creating additional tunnel to localhost:60635...
 ✓ Additional tunnel created: localhost:55823 → localhost:60635
ERROR: Error parsing reference: ghcr.io/psviderski/ucind is not a valid image reference.
 ! Cleaning up after error...

I do use the same bash version as you are using:
GNU bash, version 5.2.37(1)-release (x86_64-redhat-linux-gnu)
The only difference is that I'm using Fedora.

Bash symbol =~ is using ERE engine, which by reading that spec:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04
does not support non-greedy operator as: The behavior of multiple adjacent duplication symbols ( '+', '*', '?', and intervals) produces undefined results. and so does not support .*?

Bash symbol =~ is using ERE engine, yes, but can also be extended with platform dependent extensions...
So my guess is that fedora (and others) have some extension making bash supporting non-greedy operators and such things, that macos don't.

I suggest to change the regex in get_temp_image_name to ^([^:\/]+(:[0-9]+)?\/)?([^\/]+\/)?(.+)$ to be posix compliant and also in the same function changing the BASH_REMATCH group from 3 to 4.
@psviderski could you try this fix on your mac please ? I don't have a mac at hand (sadly).

@JonathanMbt
Copy link
Contributor Author

My 2 cents regarding this change and @tonyo's follow-up: da2720e#diff-d5e4d037c1ed36953841f496931701101aaac3efc12860de17810a6e931fad81R417

Note that when Docker does not use the containerd image store, overtime it will be filled up with XXXX-image-without-registry-prefix or just image-without-registry-prefix (before @tonyo's follow-up) images. Not sure if this is a problem but I guess it introduces some discrepancy and makes it harder to automate the cleanup commands: https://github.com/psviderski/unregistry?tab=readme-ov-file#without-containerd-image-store-default-docker-behaviour

If we don't prefix with XXXX, there is a risk to override another image that has image-without-registry-prefix name.

Ideally, we'd want to retag the image in the containerd image store as well but we can't guarantee that the remote user has permissions to talk to containerd directly.

What else can we do?

1. Do not support images with registry `HOST` that contains chars which are not allowed in `NAMESPACE`, e.g. colons `:` used to separate a port. But we can provide a clear error message in this case suggesting to manually retag the image before `pussh`ing.

2. Replace the invalid registry names with something deterministic that could be used as `NAMESPACE`, e.g.
   a. `private.registry.com:8000` -> `private.registry.com-8000` (it will stay as `private.registry.com-8000` in the containerd store, if not used by Docker, but at least it's pretty straightforward for the user how the name was produced)
   b. `private.registry.com:8000` -> `private.registry.com` YOLO? 😄
   c. `private.registry.com:8000` -> `742906a` (short hash which is IMO very unintuitive)
   d. ?

To me, 2a looks like a reasonable compromise. What do you guys think? @JonathanMbt, @tonyo

Humm that's right would be better to have something deterministic. 2a seems the better option IMO.

@tonyo
Copy link
Collaborator

tonyo commented Jul 18, 2025

2a sounds good; @JonathanMbt do you want to give it a try?

@JonathanMbt
Copy link
Contributor Author

Yup, I will ;)

@tonyo
Copy link
Collaborator

tonyo commented Jul 22, 2025

Follow-up: realized that I've misread the thread, somehow totally missed the part that it's broken on macos, and released it 🙈
Thanks @psviderski for pushing the fix (0.2.1) 👍
And thanks @JonathanMbt for the update #35

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants