Private Docker Registry
A self-hosted Docker registry with a web UI, running as a Dockge stack on TrueNAS (or any Docker host). Useful for storing images built locally — like the SSH container — so they can be reused without rebuilding from scratch.
Overview
This stack runs two containers:
- registry — the official Docker registry, with htpasswd authentication and delete support enabled
- registry-ui — a lightweight web UI (joxit/docker-registry-ui) for browsing and managing images
The registry is exposed on port 7000 (mapped from the internal 5000) and the UI
on port 7001.
Prerequisites
- Dockge running on your Docker host
htpasswdavailable on the host (part ofapache2-utilson Ubuntu/Debian, orhttpd-toolson RHEL/Fedora)- A data path for persistent storage (e.g.
/mnt/your-pool/data)
Step 1: Create the Auth Directory and Credentials
The registry uses htpasswd for basic authentication. Create the auth file before starting the stack, otherwise the registry will fail to start.
On your TrueNAS shell (or Docker host):
mkdir -p /mnt/your-pool/data/docker-registry/auth
htpasswd -Bc /mnt/your-pool/data/docker-registry/auth/htpasswd <your-username>
You’ll be prompted to set a password. The -B flag uses bcrypt hashing (recommended).
Note: The data directory for registry image layers will be created automatically at
/mnt/your-pool/data/docker-registry/datawhen the container first starts.
Step 2: Deploy with Dockge
In Dockge, create a new stack called docker-registry and paste the following:
services:
registry:
image: registry:2
container_name: docker-registry
restart: unless-stopped
ports:
- 7000:5000
volumes:
- ${DATA_PATH}/docker-registry/data:/var/lib/registry
- ${DATA_PATH}/docker-registry/auth:/auth
environment:
REGISTRY_STORAGE_DELETE_ENABLED: "true"
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
labels:
homepage.group: Dev
homepage.name: Docker Registry
homepage.icon: docker.png
homepage.description: Private container registry
registry-ui:
image: joxit/docker-registry-ui:latest
container_name: registry-ui
restart: unless-stopped
ports:
- 7001:80
environment:
SINGLE_REGISTRY: "true"
REGISTRY_TITLE: Homelab Registry
DELETE_IMAGES: "true"
SHOW_CONTENT_DIGEST: "true"
NGINX_PROXY_PASS_URL: http://registry:5000
depends_on:
- registry
labels:
homepage.group: Dev
homepage.name: Registry Browser
homepage.icon: docker.png
homepage.href: http://<truenas-ip>:7001
homepage.description: Browse container images
networks: {}
Set the environment variable
In Dockge’s env section (or a .env file), set:
DATA_PATH=/mnt/your-pool/data
Deploy the stack. Both containers should come up within a few seconds.
Step 3: Log In from Your Laptop
Before pushing or pulling images, authenticate Docker against the registry:
docker login <truenas-ip>:7000
Enter the username and password you set in Step 1.
Step 4: Push and Pull Images
Tag and push a local image
docker tag my-image:latest <truenas-ip>:7000/my-image:latest
docker push <truenas-ip>:7000/my-image:latest
Pull an image
docker pull <truenas-ip>:7000/my-image:latest
Use in a Compose file
image: <truenas-ip>:7000/my-image:latest
Step 5: Browse the Registry UI
Open http://<truenas-ip>:7001 in your browser. You can browse repositories,
inspect image tags and digests, and delete images from the UI.
Note: The UI connects to the registry through Docker’s internal network (
http://registry:5000), so it does not require the registry to be exposed externally.
Troubleshooting
Registry returns 401 Unauthorized
The htpasswd file may be missing or in the wrong location. Verify:
ls -la /mnt/your-pool/data/docker-registry/auth/htpasswd
Re-run the htpasswd command from Step 1 if needed, then restart the stack.
docker login fails with “http: server gave HTTP response to HTTPS client”
Docker requires HTTPS for registries unless the address is marked as insecure. Add the registry to your Docker daemon’s insecure registries list on any machine that needs to push/pull:
{
"insecure-registries": ["<truenas-ip>:7000"]
}
On Linux this goes in /etc/docker/daemon.json. Restart the Docker daemon after
saving:
sudo systemctl restart docker
On Docker Desktop (Mac/Windows), add it via Settings → Docker Engine.
UI shows “No repositories found” despite images being present
Confirm the NGINX_PROXY_PASS_URL in the UI service points to http://registry:5000
(the internal service name), not the external host port.