How to install neo4j in an LXD container on Ubuntu

Neo4j is a different type of database, is a graph database. It is quite cool and it is worth to spend the time to learn how it works.

The main benefit of a graph database is that the information is interconnected as a graph, and allows to execute complex queries very quickly.

One of the sample databases in Neo4j is (big part of) the content of IMDb.com (the movie database). Here is the description of some possible queries:

  • Find actors who worked with Gene Hackman, but not when he was also working with Robin Williams in the same movie.
  • Who are the five busiest actors?
  • Return the count of movies in which an actor and director have jointly worked

In this post

  1. we install Neo4j in an LXD container on Ubuntu (or any other GNU/Linux distribution that has installation packages)
  2. set it up so we can access Neo4j from our Ubuntu desktop browser
  3. start the cool online tutorial for Neo4j, which you can complete on your own
  4. remove the container (if you really wish!) in order to clean up the space

Creating an LXD container

See Trying out LXD containers on our Ubuntu in order to make the initial (one-time) configuration of LXD on your Ubuntu  desktop.

Then, let’s start with creating a container for neo4j:

$ lxc launch ubuntu:x neo4j
Creating neo4j
Starting neo4j
$ _

Here we launched a container named neo4j, that runs Ubuntu 16.04 (Xenial, hence ubuntu:x).

Let’s see the container details:

$ lxc list
+----------+---------+----------------------+------+------------+-----------+
| NAME     | STATE   | IPV4                 | IPV6 | TYPE       | SNAPSHOTS |
+----------+---------+----------------------+------+------------+-----------+
| neo4j    | RUNNING | 10.60.117.91 (eth0)  |      | PERSISTENT | 0         |
+----------+---------+----------------------+------+------------+-----------+
$ _

It takes a few seconds for a new container to launch. Here, the container is in the RUNNING state, and also has a private IP address. It’s good to go!

Connecting to the LXD container

Let’s get a shell in the new neo4j LXD container.

$ lxc exec neo4j -- sudo --login --user ubuntu
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ubuntu@neo4j:~$ sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu xenial InRelease
Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB] 
Get:4 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB] 
Get:5 http://archive.ubuntu.com/ubuntu xenial/main Sources [868 kB] 
Get:6 http://security.ubuntu.com/ubuntu xenial-security/main Sources [61.1 kB]
Get:7 http://security.ubuntu.com/ubuntu xenial-security/restricted Sources [2,288 B]
Get:8 http://archive.ubuntu.com/ubuntu xenial/restricted Sources [4,808 B] 
Get:9 http://archive.ubuntu.com/ubuntu xenial/universe Sources [7,728 kB] 
Get:10 http://security.ubuntu.com/ubuntu xenial-security/universe Sources [20.9 kB]
Get:11 http://security.ubuntu.com/ubuntu xenial-security/multiverse Sources [1,148 B]
Get:12 http://security.ubuntu.com/ubuntu xenial-security/main amd64 Packages [219 kB]
Get:13 http://security.ubuntu.com/ubuntu xenial-security/main Translation-en [92.0 kB]
Get:14 http://security.ubuntu.com/ubuntu xenial-security/universe amd64 Packages [79.1 kB]
Get:15 http://security.ubuntu.com/ubuntu xenial-security/universe Translation-en [43.9 kB]
Get:16 http://archive.ubuntu.com/ubuntu xenial/multiverse Sources [179 kB] 
Get:17 http://archive.ubuntu.com/ubuntu xenial-updates/main Sources [234 kB] 
Get:18 http://archive.ubuntu.com/ubuntu xenial-updates/restricted Sources [2,688 B] 
Get:19 http://archive.ubuntu.com/ubuntu xenial-updates/universe Sources [134 kB] 
Get:20 http://archive.ubuntu.com/ubuntu xenial-updates/multiverse Sources [4,556 B] 
Get:21 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [485 kB] 
Get:22 http://archive.ubuntu.com/ubuntu xenial-updates/main Translation-en [193 kB] 
Get:23 http://archive.ubuntu.com/ubuntu xenial-updates/universe amd64 Packages [411 kB] 
Get:24 http://archive.ubuntu.com/ubuntu xenial-updates/universe Translation-en [155 kB] 
Get:25 http://archive.ubuntu.com/ubuntu xenial-backports/main Sources [3,200 B] 
Get:26 http://archive.ubuntu.com/ubuntu xenial-backports/universe Sources [1,868 B] 
Get:27 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages [4,672 B] 
Get:28 http://archive.ubuntu.com/ubuntu xenial-backports/main Translation-en [3,200 B] 
Get:29 http://archive.ubuntu.com/ubuntu xenial-backports/universe amd64 Packages [2,512 B] 
Get:30 http://archive.ubuntu.com/ubuntu xenial-backports/universe Translation-en [1,216 B] 
Fetched 11.2 MB in 8s (1,270 kB/s) 
Reading package lists... Done
Building dependency tree 
Reading state information... Done
2 packages can be upgraded. Run 'apt list --upgradable' to see them.
ubuntu@neo4j:~$ exit
logout
$ _

The command we used to get a shell is this, sudo –login –user ubuntu

We instructed to execute (exec) in the neo4j container the command that appears after the separator.

The images for the LXD containers have both a root account and also a user account, in the Ubuntu images is called ubuntu. Both accounts are locked (no default password is available). lxc exec runs the commands in the containers as root, therefore, the sudo –login –user ubuntu command would obviously run without asking passwords. This sudo command creates a login shell for the specified user, user ubuntu.

Once we are connected to the container as user ubuntu, we can then run commands as root simply by using sudo in front of them. Since user ubuntu is in /etc/sudoers, no password is asked. That is the reason why sudo apt update was ran earlier without asking a password.

The Ubuntu LXD containers auto-update themselves by running unattended-upgrade, which means that we do not need to run sudo apt upgrade. We do run sudo apt update just to get an updated list of available packages and avoid any errors when installing, just because the package list was changed recently.

After we updated the package list, we exit the container with exit.

Installing neo4j

This is the download page for Neo4j, https://neo4j.com/download/ and we click to get the community edition.

We download Neo4j (the Linux(tar)) on our desktop. When we tried this, version 3.1.1 was available.

We downloaded the file and it can be found in ~/Downloads/ (or the localized name). Let’s copy it to the container,

$ cd ~Downloads/
$ ls -l neo4j-community-3.1.1-unix.tar.gz 
-rw-rw-r-- 1 user user 77401077 Mar 1 16:04 neo4j-community-3.1.1-unix.tar.gz
$ lxc file push neo4j-community-3.1.1-unix.tar.gz neo4j/home/ubuntu/
$ _

The tarball is about 80MB and we use lxc file push to copy it inside the neo4j container, in the directory /home/ubuntu/. Note that neo4j/home/ubuntu/ ends with a / character to specify that it is a directory. If you omit this, you get an error.

Let’s deal with the tarball inside the container,

$ lxc exec neo4j -- sudo --login --user ubuntu
ubuntu@neo4j:~$ ls -l
total 151401
-rw-rw-r-- 1 ubuntu ubuntu 77401077 Mar  1 12:00 neo4j-community-3.1.1-unix.tar.gz
ubuntu@neo4j:~$ tar xfvz neo4j-community-3.1.1-unix.tar.gz 
neo4j-community-3.1.1/
neo4j-community-3.1.1/bin/
neo4j-community-3.1.1/data/
neo4j-community-3.1.1/data/databases/

[...]
neo4j-community-3.1.1/lib/mimepull-1.9.3.jar
ubuntu@neo4j:~$

The files are now in the container, let’s run this thing!

Running Neo4j

The commands to manage Neo4j are in the bin/ subdirectory,

ubuntu@neo4j:~$ ls -l neo4j-community-3.1.1/bin/
total 24
-rwxr-xr-x 1 ubuntu ubuntu 1624 Jan  5 12:03 cypher-shell
-rwxr-xr-x 1 ubuntu ubuntu 7454 Jan 17 17:52 neo4j
-rwxr-xr-x 1 ubuntu ubuntu 1180 Jan 17 17:52 neo4j-admin
-rwxr-xr-x 1 ubuntu ubuntu 1159 Jan 17 17:52 neo4j-import
-rwxr-xr-x 1 ubuntu ubuntu 5120 Jan 17 17:52 neo4j-shared.sh
-rwxr-xr-x 1 ubuntu ubuntu 1093 Jan 17 17:52 neo4j-shell
drwxr-xr-x 2 ubuntu ubuntu    4 Mar  1 12:02 tools
ubuntu@neo4j:~$

According to Running Neo4j, we need to run “neo4j start“. Let’s do it.

ubuntu@neo4j:~$ neo4j-community-3.1.1/bin/neo4j start
ERROR: Unable to find Java executable.
* Please use Oracle(R) Java(TM) 8, OpenJDK(TM) or IBM J9 to run Neo4j Server.
* Please see http://docs.neo4j.org/ for Neo4j Server installation instructions.
ubuntu@neo4j:~$

We need Java, and the documentation actually said so. We just need the headless JDK, since we are accessing the UI from our browser.

ubuntu@neo4j:~$ sudo apt install default-jdk-headless
Reading package lists... Done
Building dependency tree 
Reading state information... Done
The following additional packages will be installed:
 ca-certificates-java default-jre-headless fontconfig-config fonts-dejavu-core java-common libavahi-client3 libavahi-common-data libavahi-common3 libcups2 libfontconfig1 libfreetype6 libjpeg-turbo8 libjpeg8
 liblcms2-2 libnspr4 libnss3 libnss3-nssdb libpcsclite1 libxi6 libxrender1 libxtst6 openjdk-8-jdk-headless openjdk-8-jre-headless x11-common
[...]
Setting up default-jdk-headless (2:1.8-56ubuntu2) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Processing triggers for systemd (229-4ubuntu16) ...
Processing triggers for ureadahead (0.100.0-19) ...
ubuntu@neo4j:~$

Now, we are ready to start Neo4j!

ubuntu@neo4j:~$ neo4j-community-3.1.1/bin/neo4j start
Starting Neo4j.
Started neo4j (pid 4123). By default, it is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /home/ubuntu/neo4j-community-3.1.1/logs/neo4j.log for current status.
ubuntu@neo4j:~$ tail /home/ubuntu/neo4j-community-3.1.1/logs/neo4j.log
nohup: ignoring input
2017-03-01 12:22:41.060+0000 INFO  No SSL certificate found, generating a self-signed certificate..
2017-03-01 12:22:41.517+0000 INFO  Starting...
2017-03-01 12:22:41.914+0000 INFO  Bolt enabled on localhost:7687.
2017-03-01 12:22:43.622+0000 INFO  Started.
2017-03-01 12:22:44.375+0000 INFO  Remote interface available at http://localhost:7474/
ubuntu@neo4j:~$

So, Neo4j is running just fine, but it has been bound on the localhost which makes it inaccessible to our desktop browser. Let’s verify again,

ubuntu@neo4j:~$ sudo lsof -i
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dhclient  225   root    6u  IPv4 110811      0t0  UDP *:bootpc 
sshd      328   root    3u  IPv4 111079      0t0  TCP *:ssh (LISTEN)
sshd      328   root    4u  IPv6 111081      0t0  TCP *:ssh (LISTEN)
java     4123 ubuntu  210u  IPv6 121981      0t0  TCP localhost:7687 (LISTEN)
java     4123 ubuntu  212u  IPv6 121991      0t0  TCP localhost:7474 (LISTEN)
java     4123 ubuntu  220u  IPv6 121072      0t0  TCP localhost:7473 (LISTEN)
ubuntu@neo4j:~$

What we actually need, is for Neo4j to bind to all network interfaces so that it becomes accessible to our desktop browser. Being in a container, the all network interfaces means to bind the only other interface, the private network that LXD created for us:

ubuntu@neo4j:~$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:16:3e:48:b7:85  
          inet addr:10.60.117.21  Bcast:10.60.117.255  Mask:255.255.255.0
          inet6 addr: fe80::216:3eff:fe48:b785/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:30029 errors:0 dropped:0 overruns:0 frame:0
          TX packets:17553 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:51824701 (51.8 MB)  TX bytes:1193503 (1.1 MB)
ubuntu@neo4j:~$

Where do we look in the configuration files of Neo4j to get it to bind to all network interfaces?

We look at the Neo4j documentation on Configuring the connectors, and we see that we need to edit the configuration file neo4j-community-3.1.1/conf/neo4j.conf

We can see that there is an overall configuration parameter for the connectors, and we can set the default_listen_address to 0.0.0.0. This 0.0.0.0 in networking terms means that we want the process to bind to all networking interfaces. Let’s remind us here that in our case of LXD containers that reside in private networking, this is OK.

# With default configuration Neo4j only accepts local connections.
# To accept non-local connections, uncomment this line:
#dbms.connectors.default_listen_address=0.0.0.0

to

# With default configuration Neo4j only accepts local connections.
# To accept non-local connections, uncomment this line:
dbms.connectors.default_listen_address=0.0.0.0

Let’s restart Neo4j and check whether it looks OK:

ubuntu@neo4j:~$ neo4j-community-3.1.1/bin/neo4j restart
Stopping Neo4j.. stopped
Starting Neo4j.
Started neo4j (pid 4711). By default, it is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /home/ubuntu/neo4j-community-3.1.1/logs/neo4j.log for current status.
ubuntu@neo4j:~$ tail /home/ubuntu/neo4j-community-3.1.1/logs/neo4j.log
2017-03-01 12:57:52.839+0000 INFO  Started.
2017-03-01 12:57:53.624+0000 INFO  Remote interface available at http://localhost:7474/
2017-03-01 13:01:58.566+0000 INFO  Neo4j Server shutdown initiated by request
2017-03-01 13:01:58.575+0000 INFO  Stopping...
2017-03-01 13:01:58.620+0000 INFO  Stopped.
nohup: ignoring input
2017-03-01 13:02:00.088+0000 INFO  Starting...
2017-03-01 13:02:01.310+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2017-03-01 13:02:02.928+0000 INFO  Started.
2017-03-01 13:02:03.599+0000 INFO  Remote interface available at http://localhost:7474/
ubuntu@neo4j:~$ sudo lsof -n -i
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dhclient  225   root    6u  IPv4 110811      0t0  UDP *:bootpc 
sshd      328   root    3u  IPv4 111079      0t0  TCP *:ssh (LISTEN)
sshd      328   root    4u  IPv6 111081      0t0  TCP *:ssh (LISTEN)
java     4711 ubuntu  210u  IPv6 153406      0t0  TCP *:7687 (LISTEN)
java     4711 ubuntu  212u  IPv6 153415      0t0  TCP *:7474 (LISTEN)
java     4711 ubuntu  220u  IPv6 153419      0t0  TCP *:7473 (LISTEN)
ubuntu@neo4j:~$

The log messages still say that Neo4j is accessible at http://localhost:7474/, which is factually correct. However, lsof shows us that it is boung to all network interfaces (the * means all).

Loading up Neo4j in the browser

We know already that in our case, the private IP address of the neo4j LXD container is 10.60.117.21. Let’s visit http://10.60.117.21:7474/ on our desktop Web browser!

It works! It asks us to log in using the default username neo4j with the default password neo4j. Then, it will ask us to change the password to something else and we are presented with the initial page of Neo4j,

The $ ▊ prompt is there for you to type instructions. According to the online tutorial at https://neo4j.com/graphacademy/online-training/introduction-graph-databases/

you can start the tutorial if you type :play movie graph and press the Run button. Therefore, load on one browser tab the tutorial and on other tab run the commands in the neo4j server from the LXD container!

Once you are done

Once you have completed the tutorial, you can keep the container in order to try out more tutorials and learn more about neo4j.

However, if you want to remove this LXD container, it can be done by running:

$ lxc stop neo4j
$ lxc delete neo4j
$ lxc list
+----------+---------+----------------------+------+------------+-----------+
|   NAME   |  STATE  |         IPV4         | IPV6 |    TYPE    | SNAPSHOTS |
+----------+---------+----------------------+------+------------+-----------+
+----------+---------+----------------------+------+------------+-----------+
$ _

That’s it. The container is gone and LXD is ready for you to follow more LXD tutorials and create more containers!

Leave a Reply

%d bloggers like this: