Reputation: 1423
I have setup my own Docker Registry, but I did not want it on the root URL so when I created the service I used the REGISTRY_HTTP_PREFIX
environment variable and set it to /registry/
, thus the URL to the registry is https://tools.example.com/registry
. This is being proxied by Nginx which has Basic Auth setup on it.
I tested access to the registry using a Browser and I was able to get it to show that there are no repositories by going to http://tools.example.com/registry/v2/_catalog
:
This led me to think that it was workoing. However when I try to login to the registry using the Docker command line, I get the Basic Auth challenge but then it fails to login because the URL is incorrect, e.g.
docker login -u russells -p xxxxxxxx https://tools.example.com/registry/
Error response from daemon: login attempt to https://tools.example.com/v2/ failed with status: 404 Not Found
As can be seen from the error, the prefix is not being added properly. SO how can I login to the registry so I can push images. Is there an environment variable or something that I am missing to make the docker login
work properly?
Update - 2017-08-12 2253 BST
I Have been playing around with the configuration a bit, but I am still not getting very far.
As requested here are my configuration files.
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
keepalive_timeout 65;
upstream docker-registry {
server registry:5000;
}
map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
'' 'registry/2.0';
}
server {
listen 15000;
server_name tools.example.com;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411
chunked_transfer_encoding on;
location /registry/ {
# Do not allow connections from docker 1.5. and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$") {
return 404;
}
auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/.htpasswd;
add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;
proxy_pass http://docker-registry/registry/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
}
My Docker Registry service is deployed as registry
and is running on the default port of 5000. Looking at this now I think I have got things confused. I do not need the registry to answer on the prefix itself, just Nginx.
For example if I leave the location set to /
then I can login, but if I change this to /registry/
then I am not able to. I am beginning to think that the two are conflicting each other.
Registry
I have not set a configuration for the Registry other than the one environment variable - REGISTRY_HTTP_PREFIX
, which maybe surplus to requirements in this setup.
Update - 2017-08-15 1100 BST
In order to test the prefix
for the registry I created a registry container with the following configuration file:
version: 0.1
auth:
htpasswd:
realm: Docker Registry
path: /auth/etc/htpasswd
storage:
filesystem:
rootdirectory: /var/lib/registry
maxthreads: 100
http:
addr: 0.0.0.0:5000
prefix: /registry/
tls:
certificate: /auth/ssl/certs/registry.cert
key: /auth/ssl/private/registry.key
As this is using self signed certificates I updated my Docker engine by placing the certificate in /etc/docker/certs.d/host-lin-01:5000
.
I then created the container with the following command:
docker run -it --rm -p 5000:5000 --name registry_test -v ~/workspaces/docker/registry/etc/registry.yml:/etc/docker/registry/config.yml -v ~/workspaces/docker/registry:/auth registry:2
If I try and login to the registry with the command:
docker login -u russells -p xxxxxx https://host-lin-01:5000/registry
I get the following error:
Error response from daemon: login attempt to https://host-lin-01:5000/v2/ failed with status: 404 Not Found
Now if I remove the perfix: /registry/
line from the registry yaml file and restart the container and then login all is well:
docker login -u russells -p xxxxxx https://turtle-host-03:5000/
Login Succeeded
What is strange, however, is that the login works for any prefix I put on the end of the login URL, e.g.
docker login -u russells -p xxxxxx https://turtle-host-03:5000/registry/fred/34
Login Succeeded
I do not understand this. I must be misunderstanding what the prefix
setting does.
Upvotes: 10
Views: 8619
Reputation: 264821
The prefix
setting in the distribution project was added for environments behind a proxy that would map the path to a hostname. It is not intended to be directly accessed from the Docker CLI. All of the endpoints in the OCI spec start at /v2
without the option to change that setting.
The docker login
is most likely stripping off the repository provided on the command, since they manage logins as a registry level, not at a repository level:
$ docker login --help
Usage: docker login [OPTIONS] [SERVER]
Authenticate to a registry.
Defaults to Docker Hub if no server is specified.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
Upvotes: 1
Reputation: 146630
You issue is the application of your Basic Auth. So you have Nginx with Basic Auth which is backed by a plain registry.
You are able to authenticate urls and see the _catalog blank json, and that make you feel it is working. But technically what is happening is that your Nginx is asking for username/password, which gets it and then passes is on to you docker registry. Which in turn has no authentication.
Now when you use docker login
you are expecting a authenticated registry but you have a authenticated nginx and non-authenticated registry. So you need to ditch the below lines of code from your nginx config
auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/.htpasswd;
Also when launching your registry you need to define the below environment variables
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
Make sure you map /auth/htpasswd
from your host to the registry container. Do this and the setup should work. Also make sure to setup the server certificates in your docker client system
Optional Changes
Next part of this answer is optional as such. Since you are using Nginx and Registry both. I would suggest you ditch the REGISTRY_HTTP_PREFIX
from your registry and change the proxy_pass
to
proxy_pass http://docker-registry/;
Upvotes: 0