Show HN: Unregistry – “docker push” directly to servers without a registry
70 comments
·June 18, 2025MotiBanana
I've been using ttl.sh for a long time, but only for public, temporary code. This is a really cool idea!
alisonatwork
This is a cool idea that seems like it would integrate well with systems already using push deploy tooling like Ansible. It also seems like it would work as a good hotfix deployment mechanism at companies where the Docker registry doesn't have 24/7 support.
Does it integrate cleanly with OCI tooling like buildah etc, or if you need to have a full-blown Docker install on both ends? I haven't dug deeply into this yet because it's related to some upcoming work, but it seems like bootstrapping a mini registry on the remote server is the missing piece for skopeo to be able to work for this kind of setup.
psviderski
You need a containerd on the remote end (Docker and Kubernetes use containerd) and anything that speaks registry API (OCI Distribution spec: https://github.com/opencontainers/distribution-spec) on the client. Unregistry reuses the official Docker registry code for the API layer so it looks and feels like https://hub.docker.com/_/registry
You can use skopeo, crane, regclient, BuildKit, anything that speaks OCI-registry on the client. Although you will need to manually run unregistry on the remote host to use them. 'docker pussh' command just automates the workflow using the local Docker.
Just check it out, it's a bash script: https://github.com/psviderski/unregistry/blob/main/docker-pu...
You can hack your own way pretty easily.
0x457
It needs docker daemon on both ends. This is just a clever way to share layer between two daemons via ssh.
nine_k
Nice. And the `pussh` command definitely deserves the distinction of one of the most elegant puns: easy to remember, self-explanatory, and just one letter away from its sister standard command.
gchamonlive
It's fine, but it wouldn't hurt to have a more formal alias like `docker push-over-ssh`.
EDIT: why I think it's important because on automations that are developed collaboratively, "pussh" could be seen as a typo by someone unfamiliar with the feature and cause unnecessary confusion, whereas "push-over-ssh" is clearly deliberate. Think of them maybe as short-hand/full flags.
psviderski
That's a valid concern. You can very easily give it whatever name you like. Docker looks for `docker-COMAND` executables in ~/.docker/cli-plugins directory making COMMAND a `docker` subcommand.
Rename the file to whatever you like, e.g. to get `docker pushoverssh`:
mv ~/.docker/cli-plugins/docker-pussh ~/.docker/cli-plugins/docker-pushoverssh
Note that Docker doesn't allow dashes in plugin commands.EricRiese
> The extra 's' is for 'sssh'
> What's that extra 's' for?
> That's a typo
someothherguyy
and prone to collision!
nine_k
Indeed so! Because it's art, not engineering. The engineering approach would require a recognizably distinct command, eliminating the possibility of such a pun.
metadat
This should have always been a thing! Brilliant.
Docker registries have their place but are overall over-engineered and an antithesis to the hacker mentality.
password4321
As a VC-funded company Docker had to make money somehow.
scott113341
Neat project and approach! I got fed up with expensive registries and ended up self-hosting Zot [1], but this seems way easier for some use cases. Does anyone else wish there was an easy-to-configure, cheap & usage-based, private registry service?
stroebs
Your SSL certificate for zothub.io has expired in case you weren’t aware.
modeless
It's very silly that Docker didn't work this way to start with. Thank you, it looks cool!
TheRoque
You can already achieve the same thing by making your image into an archive, pushing it to your server, and then running it from the archive on your server.
Saving as archive looks like this: `docker save -o may-app.tar my-app:latest`
And loading it looks like this: `docker load -i /path/to/my-app.tar`
Using a tool like ansible, you can achieve easily what "Unregistry" is doing automatically. According to the github repo, save/load has the drawback of tranfering the whole image over the network, which could be an issue that's true. And managing the images instead of archive files seems more convenient.
nine_k
If you have an image with 100MB worth of bottom layers, and only change the tiny top layer, the unregistry will only send the top layer, while save / load would send the whole 100MB+.
Hence the value.
isoprophlex
yeah i deal with horrible, bloated python machine learnings shits; >1 GB images are nothing. this is excellent, and i never knew how much i needed this tool until now.
layoric
I'm so glad there are tools like this and swing back to selfhosted solutions, especially leveraging SSH tooling. Well done and thanks for sharing, will definitely be giving it a spin.
fellatio
Neat idea. This probably has the disadvantage of coupling deployment to a service. For example how do you scale up or red/green (you'd need the thing that does this to be aware of the push).
Edit: that thing exists it is uncloud. Just found out!
That said it's a tradeoff. If you are small, have one Hetzner VM and are happy with simplicity (and don't mind building images locally) it is great.
psviderski
For sure, it's always a tradeoff and it's great to have options so you can choose the best tool for every job.
lxe
Ooh this made me discover uncloud. Sounds like exactly what I was looking for. I wanted something like dokku but beefier for a sideproject server setup.
psviderski
I'm glad the idea of uncloud resonated with you. Feel free to join our Discord if you have questions or need help
vhodges
There is also https://skateco.github.io/ which (at quick glance) seems similar
nodesocket
A recommendation for Portainer if you haven't used or considered it. I'm running two EC2 instances on AWS using portainer community edition and portainer agent and works really well. The stack feature (which is just docker compose) is also super nice. One EC2 instance; running Portainer agent runs Caddy in a container which acts as the load balancer and reverse proxy.
mountainriver
I’ve wanted unregistry for a long time, thanks so much for the awesome work!
psviderski
Met too, you're welcome! Please create an issue on github if you find any bugs
bradly
As a long ago fan of chef-solo, this is really cool.
Currently, I need to use a docker registry for my Kamal deployments. Are you familiar with it and if this removes the 3rd party dependency?
psviderski
Yep, I'm familiar with Kamal and it actually inspired me to build Uncloud using similar principles but with more cluster-like capabilities.
I built Unregistry for Uncloud but I belive Kamal could also benefit from using it.
esafak
You can do these image acrobatics with the dagger shell too, but I don't have enough experience with it to give you the incantation: https://docs.dagger.io/features/shell/
throwaway314155
I assume you can do these "image acrobatics" in any shell.
I got tired of the push-to-registry/pull-from-registry dance every time I needed to deploy a Docker image.
In certain cases, using a full-fledged external (or even local) registry is annoying overhead. And if you think about it, there's already a form of registry present on any of your Docker-enabled hosts — the Docker's own image storage.
So I built Unregistry [1] that exposes Docker's (containerd) image storage through a standard registry API. It adds a `docker pussh` command that pushes images directly to remote Docker daemons over SSH. It transfers only the missing layers, making it fast and efficient.
Under the hood, it starts a temporary unregistry container on the remote host, pushes to it through an SSH tunnel, and cleans up when done.I've built it as a byproduct while working on Uncloud [2], a tool for deploying containers across a network of Docker hosts, and figured it'd be useful as a standalone project.
Would love to hear your thoughts and use cases!
[1]: https://github.com/psviderski/unregistry
[2]: https://github.com/psviderski/uncloud