Docker private registry
Small howto to explain how to create a private Docker registry behind a Nginx proxy. My setup will focus on OpenBSD (because it’s my main system).
With your account, you will push images but they will be in public mode (you only have 1 private repository). If you are ok with this, let’s go !
Please note that you can upgrade your plan to have more private repositories (infos)
But maybe you want more private repositories or you have confidential informations or whatever reasons you want.
If you want to use a private registry, you will have 2 options :
- Use the docker image
- Build your own registry program (because you don’t want to run it in a container, because your system doesn’t have Docker (hello OpenBSD), etc…)
For the first case, please follow the documentation
We will folllow these steps:
- Install dependencies
- Create an unprivileged user to run the registry
- Build and configure the registry program
- Configure Nginx
-
Install the dependencies:
$ doas pkg_add git go nginx quirks-2.405 signed on 2018-01-08T15:59:34Z quirks-2.405: ok git-2.15.1:nghttp2-1.29.0: ok git-2.15.1:curl-7.57.0: ok git-2.15.1:p5-Error-0.17024: ok git-2.15.1:cvsps-2.1p1: ok git-2.15.1:libiconv-1.14p3: ok git-2.15.1:gettext-0.19.8.1p1: ok git-2.15.1:rsync-3.1.2p1: ok git-2.15.1: ok go-1.9.2: ok nginx-1.12.1p2:pcre-8.41: ok nginx-1.12.1p2: ok The following new rcscripts were installed: /etc/rc.d/gitdaemon /etc/rc.d/nginx /etc/rc.d/rsyncd See rcctl(8) for details. Look in /usr/local/share/doc/pkg-readmes for extra documentation.
```bash
$ doas adduser registry
Use option ``-silent'' if you don't want to see all warnings and questions.
Reading /etc/shells
Check /etc/master.passwd
Check /etc/group
Ok, let's go.
Don't worry about mistakes. There will be a chance later to correct any input.
Enter username []: registry
Enter full name []: Docker private registry user
Enter shell csh ksh nologin sh [nologin]:
Uid [1001]:
Login group registry [registry]:
Login group is ``registry''. Invite registry into other groups: guest no
[no]:
Login class authpf bgpd daemon default pbuild staff unbound
[default]:
Enter password []:
Disable password logins for the user? (y/n) [n]: y
Name: registry
Password: ****
Fullname: Docker private registry user
Uid: 1001
Gid: 1001 (registry)
Groups: registry
Login Class: default
HOME: /home/registry
Shell: /sbin/nologin
OK? (y/n) [y]:
Added user ``registry''
Copy files from /etc/skel to /home/registry
Add another user? (y/n) [y]: n
Goodbye!
```
```bash
$ doas su -s /bin/sh - registry
```
Now get the source and compile the program. Please note that since Go 1.8, you no longer need to set the GOPATH variable ([source](https://golang.org/doc/go1.8#gopath))
```bash
$ go get github.com/docker/distribution/cmd/registry
(wait....)
$ ./go/bin/registry --version
./go/bin/registry github.com/docker/distribution v2.6.0+unknown
```
In this setup, i have chosen to deploy the registry program in the homedir of the user registry. So i will create a few directories to put configurations file.
```bash
$ mkdir -p ~/base/etc ~/base/auth
```
* */home/registry/base* : root directory
* */home/registry/base/etc* : directory for the config file
* */home/registry/base/auth* : directory for the htpassword file
Of course feel free to change this 😏
Now get a default config file
```bash
$ cd ~/base/etc && wget -O config.yml https://raw.githubusercontent.com/docker/distribution/master/cmd/registry/config-example.yml
```
Edit the file to have it like this
```yaml
version: 0.1
log:
accesslog:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /home/registry/base
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
auth:
htpasswd:
realm: basic-realm
path: /home/registry/base/auth/htpasswd
```
I have just added the *auth* section and modify the *rootdirectory*.
Now, create the *htpasswd* file :
```bash
$ htpasswd -c ~/auth/htpasswd pea
New password:
Re-type new password: Adding password for user pea ```
Everything is configured. Launch the registry :
```bash
$ /home/registry/go/bin/registry serve /home/registry/base/etc/config.yml
WARN[0000] No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer.
To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable.
go.version=go1.9.2 instance.id=7dabf3ba-4a74-4d52-b8be-4480ccd3c8e4 version="v2.6.0+unknown"
INFO[0000] redis not configured go.version=go1.9.2 instance.id=7dabf3ba-4a74-4d52-b8be-4480ccd3c8e4 version="v2.6.0+unknown"
INFO[0000] Starting upload purge in 19m0s go.version=go1.9.2 instance.id=7dabf3ba-4a74-4d52-b8be-4480ccd3c8e4 version=“v2.6.0+unknown”
INFO[0000] using inmemory blob descriptor cache go.version=go1.9.2 instance.id=7dabf3ba-4a74-4d52-b8be-4480ccd3c8e4 version=“v2.6.0+unknown”
INFO[0000] listening on 0.0.0.0:5000 go.version=go1.9.2 instance.id=7dabf3ba-4a74-4d52-b8be-4480ccd3c8e4 version=“v2.6.0+unknown”
There is a warning about the *HTTP secret*. It's only important if you have multiples registries behind a load balancer. If this is the case or if you want to get red of this warning, simply add this line under *http:*
yaml
secret: YourSuperSecret
```
Your registry is now running... but not securised ! We need to setup SSL.
This setup is really basic. If you want to tune your config file, you will find more informations in the Docker [documentation](https://docs.docker.com/registry/configuration/).
NOTE: the registry program can handle TLS and Let’s Encrypt too but i’m more confident to have Nginx exposed to the world than the registry program…
server {
listen 443 http2;
listen [::]:443 http2;
server_name registry.yourdomain.tld;
ssl on;
ssl_certificate /etc/nginx/fullchain.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5000;
}
}
That’s all !
HINT : you will have to increase the value of client_max_body_size in order to upload big images.
-
Login to the repository:
% docker login -u pea registry.xxxx.xxxx Password: Login Succeeded ``` You can check that the file ~/.docker/config.json has been created with your credentials.
**WARNING**: keep this file safe and with good permissions (600).
-
Upload images :
% docker tag alpine:3.6 registry.xxx.xxxx/test:latest % % docker push registry.raveland.org/alpine:latest
The push refers to repository [registry.raveland.org/alpine] 3fb66f713c9f: Pushed latest: digest: sha256:9ab547ed4d6475a45675f8a127dae347a50957f431a003164a5d1c825868c013 size: 528 ```
-
Where are my images ?
All the images you will push to the registry will leave in /home/registry/base/docker. Be carefull to have enought disk space on your partition.
For the curious, i have chosen a quick and dirty way :
-
Create a crontab for the user registry :
$ crontab -u registry -l @reboot /usr/bin/tmux new -d -s docker "/home/registry/go/bin/registry serve /home/registry/base/etc/config.yml"