---
title: "Deploy Docker Registry | (Just Updated) Private Registry With Login, Not Open to the Internet"
description: "Private Docker registry with login. Images survive redeploys, deletes work"
category: "Storage"
url: https://railway.com/deploy/docker-registry-private
---

# Deploy Docker Registry | (Just Updated) Private Registry With Login, Not Open to the Internet

Private Docker registry with login. Images survive redeploys, deletes work

**[Deploy Docker Registry | (Just Updated) Private Registry With Login, Not Open to the Internet on Railway](https://railway.com/template/docker-registry-private)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/docker-registry-private/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Storage
- **Total deploys:** 5

## Template content

### registry

- **Image:** ghcr.io/bon5co/docker-registry-railway@sha256:40ef4b519a8cbbc88e096a7423c141681edba46306cf6deb1a0e642640972710
- **Health check:** /
- **Public domain:** Yes

## Documentation

# Deploy and Host Docker Registry on Railway

Docker Registry is the CNCF [distribution](https://github.com/distribution/distribution)
project — the reference implementation of the OCI registry API, and the same
software Docker Hub was built on. It stores and serves container images over
`docker push` and `docker pull`, with no account, no rate limit and no pull
quota, on storage you own.

This listing runs `registry:3.0.0` pinned by digest, behind **basic
authentication that is configured for you on first boot**.

## About Hosting Docker Registry

A registry is a stateful HTTP service: layers land on disk as they are pushed,
and the whole point of it is that they are still there tomorrow. Two things
therefore decide whether a hosted registry is usable, and both are easy to get
wrong.

The first is storage. Without a persistent volume the filesystem driver writes
into the container, so every redeploy silently discards every image that was
ever pushed. Here the volume is mounted at `/var/lib/registry`, and the
container refuses to start if that path is not writable — a registry that
answers its healthcheck while dropping every push is the failure that is
hardest to notice from outside.

The second is authentication. Distribution reads its entire configuration from
environment variables **except** credentials: `REGISTRY_AUTH_HTPASSWD_PATH` is a
file path, and only bcrypt hashes are accepted in it. So a registry deployed
from environment variables alone is anonymous, and on a public domain that means
anyone who finds the URL can push, pull and overwrite every tag. This image
builds that htpasswd file from `REGISTRY_USERNAME` and `REGISTRY_PASSWORD` at
boot, so the deploy is closed from its first second.

## Why Deploy Docker Registry?

- **It is private.** `docker login` is required for every push and pull.
  `REGISTRY_PASSWORD` is generated for you at deploy time; the user name is
  `admin` unless you change it.
- **Images survive redeploys.** The volume is mounted at the registry's own data
  root, and a write test runs before the port opens.
- **You can actually delete things.** `REGISTRY_STORAGE_DELETE_ENABLED=true` is
  set, so the delete API returns `202` instead of `405` and the volume is
  reclaimable. Without it a registry only ever grows.
- **The version cannot move under you.** The image is pinned by digest, so a
  redeploy six months from now runs exactly the binary you tested against your
  volume — never a storage-driver change you did not ask for.
- **No pull limits.** Docker Hub throttles anonymous and free pulls; your CI
  pulling from here does not.

## Common Use Cases

- A private registry for CI pipelines that build images on every commit, without
  paying per-seat for a hosted one.
- A cache and mirror in front of Docker Hub so builds stop failing on pull-rate
  limits.
- Distributing internal images to a team, a homelab, or a fleet of servers.
- Holding release artifacts for Railway services themselves — Railway can deploy
  from any image URL, including this one.

## Dependencies for Docker Registry Hosting

Docker Registry is a single Go binary and depends on no database, cache or
external service. It needs only a writable volume, which this template attaches.

### Deployment Dependencies

- [distribution](https://github.com/distribution/distribution) — the upstream
  project.
- [Registry configuration reference](https://distribution.github.io/distribution/about/configuration/)
- [Railway wrapper image](https://github.com/bon5co/docker-registry-railway) —
  the Dockerfile and entrypoint used here, so you can read exactly what was
  added to the upstream image.

## After deploying

Log in with `docker login `, using the user name `admin` and the
value Railway generated for the `REGISTRY_PASSWORD` variable. Then:

```bash
docker tag myapp:latest /myapp:latest
docker push /myapp:latest
docker pull /myapp:latest
```

The catalog is at `/v2/_catalog` and needs the same credentials.

To reclaim space after deleting manifests, run the garbage collector from the
service's shell:

```bash
registry garbage-collect --delete-untagged /etc/distribution/config.yml
```


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/docker-registry-private
