10
votes

I am setting up Artifactory as a Docker repository. I followed the documentation and I am able to successfully pull images from my virtual Docker repo.

However, when I try to push an image to a local repository, it fails with 501 Not Implemented error.

This is my setup:

Nginx is reverse-proxying:

artifactory.somedomain.com:8085 -> http://localhost:8081/artifactory/api/docker/docker-local/v2
artifactory.somedomain.com:8086 -> http://localhost:8081/artifactory/api/docker/docker/v2
  • docker-local is a local repository, API V2, does not force authentication. No other setting set.
  • docker is a virtual repository, aggregates docker-local and docker-remote (which just proxies to std Docker repo)

Commands run:

docker pull artifactory.somedomain.com:8086/busybox:latest 
docker tag artifactory.somedomain.com:8086/busybox artifactory.somedomain.com:8085/busybox 
docker push artifactory.somedomain.com:8085/busybox 

Results in:

The push refers to a repository [artifactory.somedomain.com:8085/busybox] (len: 1) 
2c5ac3f849df: Buffering to Disk 
Received unexpected HTTP status: 501 Not Implemented 

Any ideas what could be wrong? Thank you!

nginx.conf (The first two rules handle redirecting http in general, the last two rules handle proxying for Docker repository)

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    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;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    client_max_body_size 1G;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

        server {
                listen 80;
                server_name artifactory.somedomain.com;
                return 301 https://$server_name$request_uri;
        }

        server {
            listen 443;
            server_name artifactory.somedomain.com;

            access_log /var/log/nginx/artifactory.yourdomain.com.access.log;
            error_log /var/log/nginx/artifactory.yourdomain.com.error.log;

            ssl on;
            ssl_certificate /etc/nginx/cert/artifactory-cert-chain.crt;
            ssl_certificate_key /etc/nginx/cert/artifactory.key;

            ssl_session_timeout 5m;

            ssl_protocols SSLv3 TLSv1;
            ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
            ssl_prefer_server_ciphers on;

            location / {
                proxy_redirect http:// https://;
                proxy_set_header Host $host:$server_port;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-Ssl on;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://localhost:8081;
                proxy_pass_header Server;
                proxy_read_timeout 90;
            }
        }

        server {
            listen 8085;
            server_name artifactory.somedomain.com;

            ssl on;
            ssl_certificate /etc/nginx/cert/artifactory-cert-chain.crt;
            ssl_certificate_key /etc/nginx/cert/artifactory.key;

            access_log /var/log/nginx/artprod.company.com.access.log;
            error_log /var/log/nginx/artprod.company.com.error.log;

            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Original-URI $request_uri;
            proxy_pass_header   Server;  # To help debugging, list the server that actually did the reply rather than nginx
            proxy_read_timeout 900;

            client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads

            # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
            chunked_transfer_encoding on;

            location /v2 {
                # Do not allow connections from docker 1.5 and earlier
                # docker pre-1.6.0 did not properly set the user agent on ping
                if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))).*$" ) {
                   return 404;
                }

                proxy_pass http://localhost:8081/artifactory/api/docker/docker-local/v2;
        }
    }

        server {
            listen 8086;
            server_name artifactory.somedomain.com;

            ssl on;
            ssl_certificate /etc/nginx/cert/artifactory-cert-chain.crt;

            ssl_certificate_key /etc/nginx/cert/artifactory.key;

            access_log /var/log/nginx/artprod.company.com.access.log;
            error_log /var/log/nginx/artprod.company.com.error.log;

            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Original-URI $request_uri;
            proxy_pass_header   Server;  # To help debugging, list the server that actually did the reply rather than nginx
            proxy_read_timeout 900;

            client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads

            # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
            chunked_transfer_encoding on;

            location /v2 {
                # Do not allow connections from docker 1.5 and earlier
                # docker pre-1.6.0 did not properly set the user agent on ping
                if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))).*$" ) {
                return 404;
                }

                proxy_pass http://localhost:8081/artifactory/api/docker/docker/v2;
        }
    }

}

NginX's access log shows this for each request

192.168.33.65 - - [02/Nov/2015:13:04:56 +0100] "GET /v2/ HTTP/1.1" 200 12 "-" "docker/1.8.3 go/go1.4.2 git-commit/f4bf5c7 kernel/4.1.10-boot2docker os/linux arch/amd64"
192.168.33.65 - - [02/Nov/2015:13:04:57 +0100] "HEAD /v2/busybox/blobs/sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 HTTP/1.1" 404 0 "-" "docker/1.8.3 go/go1.4.2 git-commit/f4bf5c7 kernel/4.1.10-boot2docker os/linux arch/amd64"
192.168.33.65 - - [02/Nov/2015:13:04:57 +0100] "POST /v2/busybox/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/1.8.3 go/go1.4.2 git-commit/f4bf5c7 kernel/4.1.10-boot2docker os/linux arch/amd64"
1
It looks like your ngnix only passes GET requests, but not PUT requests. Can you please post the ngnix config?JBaruch
Sure, I updated the question.Martin Melka
However, I think this is not the case. I have used curl -XPUT to successfully push artifacts to Artifactory (albeit not to a Docker registry)Martin Melka
Which version of the Docker client are you using? do you see the failing request in the NginX and Artifactory logs (error, access etc.)?Dror Bereznitsky
Version 1.8.3. NginX's access log shows some info. I appended it to the question.Martin Melka

1 Answers

5
votes

The issue was with NginX's configuration. The sample one provided in the Artifactory documentation assumes you are using the HTTPS port 443 to connect to the repository.

If you are using a different port, you need to edit the listen and proxy_set_header Host directive to include the port.

server {
    listen <port>;
    ...
    proxy_set_header Host $host:<port>;
    ...
}