Sometimes you need your own docker-registry to just try out new things or to avoid downloading stuff again and again from the internet. I tried to build a docker-compose recipe to setup my own private registry.

Docker installation required

Docker must be installed on your system.
$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:34 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:29:19 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

You’ll need a working directory where docker-compose.yml file and certificates are stored in, so please create a folder my-registry as shown below:

$ mkdir -p $HOME/my-registry/certs        # store your certificates
$ mkdir -p $HOME/my-registry/registry     # store your registry data
$ cd $HOME/my-registry

Create self signed certificate

Now you should create a self-signed certificate for new docker-registry. These files are stored in previously created certs/ folder so it can be mounted into docker-registry container later.

$ openssl req -newkey rsa:4096 -nodes -sha256 -x509 -days 365 \
    -keyout certs/docker-registry.key \
    -out certs/docker-registry.crt

Registry docker-compose file

I really like docker-compose to build services. So I tried to use it for my private registry as well. Please touch a file called docker-compose.yml in current directory:

$ touch docker-compose.yml

and fill in following content:

registry:
  container_name: docker-registry
  restart: always
  image: registry:2
  ports:
    - 5000:5000
  environment:
    REGISTRY_HTTP_SECRET: replace_with_your_secret
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/docker-registry.crt
    REGISTRY_HTTP_TLS_KEY: /certs/docker-registry.key
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
  volumes:
    - ./registry:/var/lib/registry
    - ./certs:/certs

Now your file structure should look like:

.
├── certs
│   ├── docker-registry.crt
│   └── docker-registry.key
├── docker-compose.yml
└── registry

Running registry

If you run docker-compose up it will start to pull docker-registry image and run it in foreground. By adding -d you can send it to background.

$ docker-compose up -d
Pulling registry (registry:2)...
2: Pulling from library/registry
...
Status: Downloaded newer image for registry:2
Creating docker-registry

After your registry was started it should appear as running container:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
9ec14708e2dc        registry:2          "/bin/registry /etc/d"   48 seconds ago      Up 47 seconds       0.0.0.0:5000->5000/tcp   docker-registry

Pushing to your registry

You should be able to push your tagged images onto this running docker-registry server.

$ docker pull busybox
$ docker tag busybox localhost:5000/busybox
$ docker push localhost:5000/busybox

If this fails, you may have to modify your docker startup line/script to accept insecure registries by adding --insecure-registry localhost:5000.

Much more

This is a very simple tutorial, there’s much more docker-registry 2.0 can do, please visit docker-hub to find more options how to run docker-registry 2.0 container.