Why I Chose Nexus Repository Over Artifactory When Using Docker

Asaf Mesika - Featured Image

Asaf Mesika, Author

A couple of days ago, I needed to setup Logz.io’s first internal Maven repository. We’re a youngish company in the field of Log Analysis and haven’t needed a Maven repository so far. We rely heavily on open source technologies but the need to fork and patch these technologies arises all too often.

Until the merge takes place, the code’s artifacts need to be hosted somewhere accessible to the build system — internal Maven Repository to the rescue.

Editor’s Note: Asaf Mesika is Core Senior Developer at Logz.io and participates in the Israeli Java Community User Group on meetup.com. He has “bare minimum patience” with open source products.

Open Source Repository Choices

When trying open source products, especially in Startups, you have a very low threshold of patience for things not working. I think open source products must invest in the onboarding user experience as much as possible.

I am aware of two open source products: Artifactory by JFrog and Nexus Repository Manager by Sonatype. I leaned to Artifactory since I remember it being more feature rich, and being used by many popular open source products.

In this article I describe a case study of how I failed to install Artifactory using Docker following their official guide and compared that 3 min installation of Nexus.

Chapter 1: Artifactory Installation

I searched for “Installing Artifactory using Docker” and got to this official guide.

First thing I created a couple of directories they advised as highly recommended to mount:

mkdir -p /var/artifactory/data
mkdir /var/artifactory/logs
mkdir /var/artifactory/backup
mkdir /var/artifactory/etc

I then continued to run the docker image:

docker run — name artifactory -p 80:8081 -e “ARTIFACTORY_HOME=/var/opt/jfrog/artifactory” -v /var/artifactory/data:/var/opt/jfrog/artifactory/data -v /var/artifactory/logs:/var/opt/jfrog/artifactory/logs -v /var/artifactory/backup:/var/opt/jfrog/artifactory/backup -v /var/artifactory/etc:/var/opt/jfrog/artifactory/etc jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:latest

I got this first error message:

Unable to find image ‘jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:latest’ locally
latest: Pulling from jfrog/artifactory-oss
a2c33fe967de: Pull complete
b527c153b530: Pull complete
63f70f5a23b8: Pull complete
333ee72b10ae: Pull complete
3297c49bbe77: Pull complete
e2f19b824bda: Pull complete
e907a4f03f92: Pull complete
25981fad9a81: Pull complete
37226b35a736: Pull complete
2d90bd8d7cb9: Pull complete
ac1fc7130559: Pull complete
4f43cce3cb41: Pull complete
Digest: sha256:d8f0022b19a3f88a01565d970a0cc0d72e851700f6eded920388c016bc1d25dc
Status: Downloaded newer image for jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:latest
nginx: unrecognized service
grep: /var/opt/jfrog/artifactory/etc/default: No such file or directory
** ERROR: Artifactory pid destination ARTIFACTORY_PID was not set in /etc/opt/jfrog/artifactory/default ! Please add it!
  1. I don’t understand why nginx is an unrecognized service
  2. The script tried to grep a file named default in /var/opt/jfrog/artifactory/etc — the directory I was told to mount and failed. It makes sense it failed since the directory is empty.

The main error is that ARTIFACTORY_PID is missing. At first I was sure I was missing an environment variable in my run command. I googled the error and found “How can I use own located folders as volumes in docker artifactory container?” Stackoverflow question which explained that inside the docker container there are files inside etc folder which get override due to the volume mount of etc folder. They suggested a fix to run the docker with command /bin/bash, copy the contents of the folder to my host etc folder, and then continue. That was way too much work for me.

I settled by removing the mount of etc folder and continue. I ran the command again without that mount and got:

nginx: unrecognized service
Starting Artifactory tomcat as user artifactory…
Max number of open files: 524288
Using ARTIFACTORY_HOME: /var/opt/jfrog/artifactory
Using ARTIFACTORY_PID: /var/opt/jfrog/run/artifactory.pid
Creating directory /var/opt/jfrog/artifactory/logs/catalina
mkdir: cannot create directory `/var/opt/jfrog/artifactory/logs/catalina’: Permission denied
Creating directory /var/opt/jfrog/artifactory/temp
Creating directory /var/opt/jfrog/artifactory/work
touch: cannot touch `/opt/jfrog/artifactory/tomcat/logs/catalina.out’: No such file or directory
/opt/jfrog/artifactory/tomcat/bin/catalina.sh: line 401: /opt/jfrog/artifactory/tomcat/logs/catalina.out: No such file or directory
** ERROR: Artifactory Tomcat server did not start. Please check the logs

So it couldn’t create a directory under the logs folder I created and mounted. This is something I did many times, including with Graphite and logz.io’sjmx2graphite.

I checked permissions on those directories. I was running as root, and the directories had write access as root — which was the same user I used when I was running the docker Artifactory image.

I googled some more to learn about how docker treats permissions and about this problem in Artifactory and saw that they run their tomcat application as “artifactory” user, which may be the reason why they can’t write to this directory.

It didn’t make sense to me to change access to a user which doesn’t exists on the host, only by using its internal unix user id (only residing inside the docker image). I discarded the idea of giving write access to ALL which doesn’t sound very secure to me.

At this point, after spending roughly an hour, I gave up and tried the second option: Nexus.

Chapter 2: Sonatype Nexus Repository Manager

Sonatype Nexus Repository Manager is a product I’ve worked with for many years dating back to 2009 when I was working in Cotendo and also in my time at Akamai . I was very pleased with it, so I tried to do the same with it.

I got to this installation article. I immediately gave them bonus points for being completely open source about it — a github repo with its Dockerfile and a very good readme. What I love about it is that you can take that Dockerfile and create your own version with your config very easily.

Compare this with Artifactory:

  • You can’t find their Dockerfile (Try googling “artifactory docker dockerfile”)
  • Their installation guide is inside a wiki which doesn’t allow commenting, so people end up improving this doc using StackOverflow, as opposed to comments or just Pull Request / Issues on the repo hosting the Dockerfile

I ran the following command to create a volume container hosting the persisted files, per the guide suggestion:

docker run -d — name nexus-data sonatype/nexus echo “data-only container for nexus”

Next I ran the Nexus image:

docker run -d -p 80:8081 — name nexus — volumes-from nexus-data sonatype/nexus

Boom! I’m done! 3 minutes and I happily surf to their admin page.


Sonatype did some great work with the UX of installing their open source product using Docker. Artifactory has some way to go to achieve this. Here are suggestions to them:

  • Put your Dockerfile as git repository
  • Open the installation guide to comments or place it as README.MD in the git repo
  • Fix all the problems — make it truly 3 minutes installation for first time users.
The following two tabs change content below.

Asaf Mesika

Core Senior Developer at Logz.io
Asaf Mesika is a core software engineer at Logz.io. He's combining his passion for clean code, 15 years of experience and appreciation for great team work to build a a truly outstanding open-source based Log Management product. Asaf previously worked at Akamai, developing a real time data pipeline and query engine for Akamai's scale security product. Asaf is also the co-founder of Java.IL, the Israeli Java User Group, fostering a a thriving community since 2010.

Latest posts by Asaf Mesika (see all)


One Comment;

  1. Pingback: Set up your own Continuous Delivery stack | The Pragmatic Integrator