Deploying a Docker image to Artifactory with Self-Signed SSL Certificates

Angello Maggio
6 min readJan 17, 2018

Artifactory is the top tool in the market for storing your binaries. It essentially provides you with as many private repositories for as many package types as you need. Setting up a Docker repository in Artifactory versions before 5.8 can be a bit of a pain if you don’t already have a reverse proxy set up. Docker will only accept HTTPS connections, so you need to have SSL certificates going on for it to work. On this tutorial I’ll show you how to get your Docker registry working on Artifactory with a self-signed certificate in pretty easy steps.

This will all be done on an Ubuntu 16.04 virtual machine with not too many resources (4GB of RAM and an ok processor, requirements may depend on what you intend to use Artifactory for.)

First let’s get started wth the basic auto-setup of a Docker repository. This will give us a local, virtual, remote, and distribution (Bintray) Docker repo.

If you are following along with a different package type, this shouldn’t be much different

We’ll be pushing our builds into docker-local in this case.

The next step is to set up a reverse proxy. This is due to the fact that with Docker you cannot use a context path when providing the registry path, and also Docker will use HTTP against HTTPS.

So we’ll set up an NGINX now. For this case we’ll be using a simple Ubuntu installation using apt-get, but you can also install through Docker or other OS-dependent executables.

$ sudo apt-get install nginx

Now we will go into the nginx folder at /etc/nginx/ and create/cd into a certs folder where we will make our self-signed certificates and keys for Nginx. Technically this folder can be anywhere, but we’ll put it here to make our lives easier and not get it lost elsewhere.

$ cd /etc/nginx/ && mkdir certs && cd certs

Now inside our certs folder we will run the following command to create our certificates and keys:

$ openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt

Fill out the prompts, and make sure that you remember the Common Name field, which we will use when setting up Nginx with Artifactory. For this case I used “.*my-wildcard-subdomain”.

Perfect, now we have our .crt and .key files. Let’s head to Artifactory and create our Nginx configuration. Let’s first do it for Pro.

Go to Artifactory UI → Admin → Configuration → Reverse Proxy

Fill in the names accordingly. We set the port to be exposed as 8082, but if you used a different one, change accordingly (default tends to be 8081.)

For public server name we will use the value we set a bit earlier (without the .* part of it.)

Now for the rest of the setting we will do according to the following image:

Here we enable HTTPS and provide the path to our SSL Key and SSL Certificate. We also set the reverse proxy method as Sub Domain.

Go ahead and save, then click “view” and copy the configuration created by Artifactory.

Put the content of this configuration file in a new file you create at /etc/nginx/sites-enabled/

We’ll call it artifactory.conf

$ sudo vim /etc/nginx/sites-enabled/artifactory.conf

and we’ll paste accordingly. Please comment the line that says “ssl_prefer_server_ciphers on;” as it is already set on the default nginx configuration and will conflict. You have something like the following:

###########################################################
## this configuration was generated by JFrog Artifactory ##
###########################################################
## add ssl entries when https has been set in config
ssl_certificate /etc/nginx/certs/domain.crt;
ssl_certificate_key /etc/nginx/certs/domain.key;
ssl_session_cache shared:SSL:1m;
## ssl_prefer_server_ciphers on;
## server configuration
server {
listen 443 ssl;
listen 80 ;
server_name ~(?<repo>.+)\.my-wildcard-subdomain my-wildcard-subdomain;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
## access_log /var/log/nginx/my-wildcard-subdomain-access.log timing;
## error_log /var/log/nginx/my-wildcard-subdomain-error.log;
rewrite ^/$ /artifactory/webapp/ redirect;
rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;
rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2;
chunked_transfer_encoding on;
client_max_body_size 0;
location /artifactory/ {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
if ( $request_uri ~ ^/artifactory/(.*)$ ) {
proxy_pass http://localhost:8082/artifactory/$1;
}
proxy_pass http://localhost:8082/artifactory/;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Now we need to change our /etc/hosts files to map our IP address to each Docker repository.

The following matches my IP address (got it by running the command ifconfig)

Notice the pattern <my_repo>.<my_wildcard_subdomain> when declaring the repositories, which reflects the part of our Nginx configuration that states server_name ~(?<repo>.+)\.my-wildcard-subdomain my-wildcard-subdomain

And we are almost ready to be able to push and pull. We need to create one more file to tell the Docker daemon where to push to and deploy from.

$ sudo vim /etc/docker/daemon.json

And add the following to this file:

{
"insecure-registries":["docker.my-wildcard-subdomain","docker-local.my-wildcard-subdomain", "docker-remote.my-wildcard-subdomain"]
}

Here we are essentially telling Docker that these locations are accepted insecure registries (self-signed certificates.) This is why I recommend using a virtual Docker repo to aggregate the other repos, so that you don’t have to declare a repo every time you add one.

And that’s essentially it! Let’s try it out. First let’s try a Docker login in the following manner

$ docker login docker.my-wildcard-subdomain

Enter your username and password and you should get a “Login Succeeded.” Hopefully it all goes well so far (leave a comment with your errors if you need more help!) Now we can get to pulling an image from Docker. We do so in the form $ docker pull <repo>.<wildcard subdomain>/<image_name>:<tag>

e.g $ docker pull docker.my-wildcard-subdomain/hello-world:latest

This should be the output of your the pull

$ docker pull docker.my-wildcard-subdomain/hello-world:latest
latest: Pulling from hello-world
9a0669468bf7: Pull complete
Digest: sha256:c39f10a159696100a2c30a9ecbdc927363613664d65dff5b928291440f75a76b
Status: Downloaded newer image for docker.my-wildcard-subdomain/hello-world:latest

Being that the only remote we have at the moment is docker-remote, this image should be cached in your docker-remote-cache. Let’s take a look at Artifactory and find out if it worked out:

Ta-dah! It works! Now you can successfully pull a Docker image and cache it with Artifactory. Let’s now try to push an image into our local repository with the Docker client.

Try pushing and pulling other images. Look at the way Artifactory stores the layers within each image and you may notice that it displays the SHA256 value. This is very useful when storing many images, as repeated layers between images are shared and only stored once thanks to Artifactory’s checksum-based storage.

I hope this has been useful to you, and if there’s any difficulty please feel free to leave a message or to upgrade to Artifactory 5.8.2 to take advantage of the proxy-less Docker registries.

Until the next time!

--

--