docker ยท containers

Self hosted Docker image registry over SSH tunnel

As a part of my ongoing effort to learn container based application deployment, I have run into the need for a image registry. Most use DockerHub for this purpose. I want to self host and learn how to set all this stuff up.

Here’s an outline of what this document will cover:

  1. Get registry configured on remote server
  2. Setup socket activated SSH tunnel to access registry
  3. Configure local container tools to know about registry

I will be using the official Docker registry image and my local tool is podman. I use systemd --user to manage my auto start and scheduled tasks, and it also supports socket activated services so it will be ideal for automating opening the SSH tunnel when I need it.

Registry on remote server

Login to your server. If you don’t have Docker or another container runtime installed, do that now. Run the following command:

# docker run -d -p 127.0.0.1:5000:5000 --restart=always --name registry registry

This will pull down the registry container image and start the container with it’s port mapped to localhost. This is important because we don’t want the registry available on any other network interfaces.

Socket activated ssh tunnel

You will need to create two files in ~/.config/systemd/user/, a service file and a socket file. Here’s the socket file:

registry-proxy.socket

[Socket]
ListenStream=127.0.0.1:5000
Accept=no

[Install]
WantedBy=default.target

registry-proxy.service

[Unit]
Description=SSH proxy to my private container image registry

[Service]
ExecStart=-ssh -T -L 5000:localhost:5000 [email protected]
StandardInput=socket

Replace user and example.com with the username and host for your remote server.

Run the following to bring up the service and have it start listening on login:

systemctl --user enable registry-proxy.socket
systemctl --user start registry-proxy.socket

Configure Podman to access registry

Edit your registries.conf and change this part:

[registries.insecure]
registries = []

to

[registries.insecure]
registries = ['localhost:5000']

We are adding it to the insecure registries list because we have not configured TLS in the registry. This is fine in this case, because SSH provides both authentication and transport security.

Published:
comments powered by Disqus