Show HN:Unregistry——无需注册表,直接将镜像“docker push”到服务器
Show HN: Unregistry – “docker push” directly to servers without a registry

原始链接: https://github.com/psviderski/unregistry

Unregistry 提供了一种简单高效的方式,通过 SSH 直接将 Docker 镜像传输到远程服务器,避免了传统镜像仓库的复杂性。它无需公共仓库、自建仓库或低效的 `save/load` 方法。只需一条命令 (`docker pussh myapp:latest user@server`),它就能建立 SSH 隧道,在远程服务器上启动一个临时的 unregistry 容器,并仅推送缺失的镜像层。 这种“Docker 镜像的 rsync”方法避免了不必要的数据传输和资源消耗。安装非常简单,可以通过 Brew 或直接下载,需要一个 Docker CLI 插件符号链接。其用例包括部署到生产服务器、简化 CI/CD 管道以及在隔离环境中分发镜像。对于独立的本地仓库使用,Unregistry 可以运行在容器中,通过端口暴露以进行本地推送。其核心功能基于 Docker Distribution,并受 Spegel 的启发,是一个强大且轻量级的镜像传输解决方案。

Psviderski 推出了 Unregistry,这是一个绕过传统 Docker registry 工作流程的部署工具。它允许通过 SSH 直接将 Docker 镜像推送到远程 Docker daemon,利用 Docker 本身已有的镜像存储。`docker pussh` 命令可以高效地只传输缺失的层,从而加快部署速度。它的工作原理是在远程主机上临时启动一个 unregistry 容器,通过 SSH 隧道推送镜像,然后进行清理。 一些用户表达了兴趣。一位用户将其与 chef-solo 作比较,并询问其与 Kamal 部署的兼容性,认为它可以消除对第三方 registry 的需求。另一位用户提供了一个基本但效率较低的替代方案,使用 `docker save` 和 `docker load`。其他用户询问了它与 Skopeo 的相似之处,以及对 Docker Compose 的潜在支持,特别是同时推送 compose 文件中定义的多个容器的能力。创建者正在考虑添加更多功能。
相关文章

原文

Unregistry is a lightweight container image registry that stores and serves images directly from your Docker daemon's storage.

The included docker pussh command (extra 's' for SSH) lets you push images straight to remote Docker servers over SSH. It transfers only the missing layers, making it fast and efficient.

docker-pussh-demo.mp4

You've built a Docker image locally. Now you need it on your server. Your options suck:

  • Docker Hub / GitHub Container Registry - Your code is now public, or you're paying for private repos
  • Self-hosted registry - Another service to maintain, secure, and pay for storage
  • Save/Load - docker save | ssh | docker load transfers the entire image, even if 90% already exists on the server
  • Rebuild remotely - Wastes time and server resources. Plus now you're debugging why the build fails in production

You just want to move an image from A to B. Why is this so hard?

docker pussh myapp:latest user@server

That's it. Your image is on the remote server. No registry setup, no subscription, no intermediate storage, no exposed ports. Just a direct transfer of the missing layers over SSH.

Here's what happens under the hood:

  1. Establishes SSH tunnel to the remote server
  2. Starts a temporary unregistry container
  3. Forwards a random localhost port to the unregistry port over the tunnel
  4. docker push to unregistry through the forwarded port, transferring only the layers that don't already exist remotely. The transferred image is instantly available on the remote Docker daemon
  5. Stops the unregistry container and closes the SSH tunnel

It's like rsync for Docker images — simple and efficient.

Note

Unregistry was created for Uncloud, a lightweight tool for deploying containers across multiple Docker hosts. We needed something simpler than a full registry but more efficient than save/load.

brew install psviderski/tap/docker-pussh

After installation, to use docker-pussh as a Docker CLI plugin (docker pussh command) you need to create a symlink:

mkdir -p ~/.docker/cli-plugins
ln -sf $(brew --prefix)/bin/docker-pussh ~/.docker/cli-plugins/docker-pussh

macOS/Linux via direct download

# Download the latest version
curl -sSL https://raw.githubusercontent.com/psviderski/unregistry/main/docker-pussh \
  -o ~/.docker/cli-plugins/docker-pussh

# Make it executable
chmod +x ~/.docker/cli-plugins/docker-pussh

Windows is not currently supported, but you can try using WSL 2 with the above Linux instructions.

Push an image to a remote server. Please make sure the SSH user has permissions to run docker commands (user is root or non-root user is in docker group). If sudo is required, ensure the user can run sudo docker without a password prompt.

docker pussh myapp:latest [email protected]

With SSH key authentication if the private key is not added to your SSH agent:

docker pussh myapp:latest [email protected] -i ~/.ssh/id_rsa

Using a custom SSH port:

docker pussh myapp:latest user@server:2222

Push a specific platform for a multi-platform image. The local Docker has to use containerd image store to support multi-platform images.

docker pussh myapp:latest user@server --platform linux/amd64

Deploy to production servers

Build locally and push directly to your production servers. No middleman.

docker build --platform linux/amd64 -t myapp:1.2.3 .
docker pussh myapp:1.2.3 deploy@prod-server
ssh deploy@prod-server docker run -d myapp:1.2.3

Skip the registry complexity in your pipelines. Build and push directly to deployment targets.

- name: Build and deploy
  run: |
    docker build -t myapp:${{ github.sha }} .
    docker pussh myapp:${{ github.sha }} deploy@staging-server

Homelab and air-gapped environments

Distribute images in isolated networks without exposing them to the internet.

docker pussh image:latest [email protected]
  • Docker CLI with plugin support (Docker 19.03+)
  • OpenSSH client
  • Docker is installed and running
  • SSH user has permissions to run docker commands (user is root or non-root user is in docker group)
  • If sudo is required, ensure the user can run sudo docker without a password prompt

Tip

The remote Docker daemon works best with containerd image store enabled. This allows unregistry to access images more efficiently.

Add the following configuration to /etc/docker/daemon.json on the remote server and restart the docker service:

{
  "features": {
    "containerd-snapshotter": true
  }
}

Running unregistry standalone

Sometimes you want a local registry without the overhead. Unregistry works great for this:

# Run unregistry locally and expose it on port 5000
docker run -d -p 5000:5000 --name unregistry \
  -v /run/containerd/containerd.sock:/run/containerd/containerd.sock \
  ghcr.io/psviderski/unregistry

# Use it like any registry
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest

Need custom SSH settings? Use the standard SSH config file:

# ~/.ssh/config
Host prod-server
    HostName server.example.com
    User deploy
    Port 2222
    IdentityFile ~/.ssh/deploy_key

# Now just use
docker pussh myapp:latest prod-server

Found a bug or have a feature idea? We'd love your help!

Inspiration & acknowledgements

  • Spegel - P2P container image registry that inspired me to implement a registry that uses containerd image store as a backend.
  • Docker Distribution - the bulletproof Docker registry implementation that unregistry uses as a base.

联系我们 contact @ memedata.com