Docker-compose deploying Neo4j with APOC

Introduction

Although the number of people using Neo4j has increased, it is still unrecognized. Since there is Neo4j Desktop on Windows, it is not inconvenient to use, but if you create a simple application and distribute it to the team, it will take a lot of space to create an image, so it is easier to use Docker. Especially when doing remote work like now. So, when I tried to distribute it as a set with the application with docker-compose, there was not much docker information of neo4j, so I checked it ~~ I will post what worked in various ways as a reminder.

Folder structure

https://github.com/MichitoIchimaru/neo4j_docker-compose

Folder
│  docker-compose.yml
├─ docker
│   └─neo4j
│      Dockerfile
│      background.sh
│      init.sh
│      init.cypher
└─volumes
   └─neo4j
      └─plugins
         apoc.jar

docker-compose.yml

docker-compose.yml


version: "3"

networks:
  app_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.30.0.0/24

services:
  neo4j:
    container_name: neo4j
    build: ./docker/neo4j
    volumes:
      - ./volumes/neo4j/data:/data
      - ./volumes/neo4j/plugins:/plugins
      - ./volumes/neo4j/logs:/logs
      - ./volumes/neo4j/import:/import
      - ./volumes/neo4j/init:/init
    ports:
      - "7474:7474"
      - "7687:7687"
    environment:
#      - NEO4JLABS_PLUGINS=["apoc"]
      - NEO4J_apoc_export_file_enabled=true
      - NEO4J_apoc_import_file_enabled=true
      - NEO4J_apoc_uuid_enabled=true
      - NEO4J_dbms_security_procedures_unrestricted=apoc.*
      - NEO4J_dbms_security_procedures_whitelist=apoc.*
      - NEO4J_dbms_memory_heap_initial__size=512m
      - NEO4J_dbms_memory_heap_max__size=2G
      - NEO4J_dbms_default__listen__address=0.0.0.0
      - NEO4J_dbms_connector_bolt_listen__address=:7687
      - NEO4J_dbms_connector_http_listen__address=:7474
      - NEO4J_dbms_connector_bolt_advertised__address=:7687
      - NEO4J_dbms_connector_http_advertised__address=:7474
      - NEO4J_dbms_allow__upgrade=true
      - NEO4J_dbms_default__database=neo4j
      - NEO4J_AUTH=neo4j/p@ssw0rd
      - EXTENSION_SCRIPT=/tmp/background.sh
    restart: unless-stopped
    networks:
      app_net:
        ipv4_address: 172.30.0.3
Commentary
#      - NEO4JLABS_PLUGINS=["apoc"]

If you uncomment this part, apoc.jar will be automatically downloaded from the Internet. This time, apoc.jar is stored in the volumes / neo4j / plugins folder from the beginning, so it is not necessary to download it, so I commented it out. Downloading apoc.jar takes a lot of time, so using the one downloaded in advance can shorten the startup time. However, there is one benefit to enabling this feature. This time, neo4j: 4.1.3 (latest as of 2020/10/15 is 4.1.3) is used for Neo4j Docker image, but since there is a version of apoc.jar corresponding to neo4j version, it is combined. It may not work depending on the version. If you uncomment this, apoc.jar corresponding to the Neo4j image you are using will be automatically identified and installed.

      - NEO4J_AUTH=neo4j/p@ssw0rd

Set neo4j password

      - EXTENSION_SCRIPT=/tmp/background.sh

I didn't understand this EXTENSION_SCRIPT. The Neo4j manual doesn't say what it's used for, and other people's articles say it's a script that runs after Neo4j starts. Looking at the actual behavior, it seems that it is executed before Neo4j is started rather than after it is started. Moreover, it seems that Neo4j will not start unless this script ends normally. Therefore, this time, init.sh is executed (with &) in background.sh. Then Neo4j will start up safely, and init.sh will wait for Neo4j to start up in the background and set up the initial data. By the way, running init.sh with & in EXTENSION_SCRIPT didn't work.

Dockerfile

FROM neo4j:4.1.3

RUN apt-get update
RUN apt-get install -y curl
COPY init.cypher /tmp/init.cypher
COPY background.sh /tmp/background.sh
COPY init.sh /tmp/init.sh
RUN chmod -v +x /tmp/background.sh
RUN chmod -v +x /tmp/init.sh

When the neo4j image is deployed, the package list of apt-get is empty, so the package cannot be installed unless apt-get update is executed once. Here, curl is installed to check the startup of Neo4j (check if Cypher can be executed). If you are in a Proxy environment, add ʻENV http_proxy http: // hogehoge` etc. here and it should work.

background.sh

background.sh


#!/bin/bash

/tmp/init.sh &

As explained above, a shell that you just want to specify EXTENSION_SCRIPT and run init.sh in the background. This is init.sh, and I feel that background.sh is more correct than init.sh, which will be described later.

init.sh

init.sh


#!/bin/bash

if [ -f /init/done ]; then
    echo "The initialization process is already completed." >> /init/setup.log
    exit 1
fi

COUNT=1

while [ $COUNT -lt 20 ]; do

  status_code=$(curl --write-out %{http_code} --silent --output /dev/null localhost:7474)
  if [[ "$status_code" = 200 ]] ; then
    touch /init/done
    cypher-shell -u neo4j -p p@ssw0rd -f /tmp/init.cypher
    echo "The initialization process is complete." >> /init/setup.log
    exit 1
  else
    echo "The neo4j service has not started yet. [$COUNT]" >> /init/setup.log
  fi

  COUNT=$(expr $COUNT + 1)
  sleep 10s

done

exit 0

This shell is a script for inputting initial data to the started Neo4j. However, since this script is executed every time docker-compose is executed, a file called / init / done is created when it is executed for the first time, and if that file exists, it ends without doing anything.

Commentary
if [ -f /init/done ]; then
    echo "The initialization process is already completed." >> /init/setup.log
    exit 1
fi

Check the existence of / init / done in this part, and if there is, end, if not, perform subsequent processing.

while [ $COUNT -lt 20 ]; do

Retry 20 times (strictly 19 times with this code) until Neo4j starts.

  status_code=$(curl --write-out %{http_code} --silent --output /dev/null localhost:7474)

Access http: // localhost: 7474 with curl and get the HTTP response code.

  if [[ "$status_code" = 200 ]] ; then
    touch /init/done
    cypher-shell -u neo4j -p p@ssw0rd -f /tmp/init.cypher
    echo "The initialization process is complete." >> /init/setup.log
    exit 1
  else
    echo "The neo4j service has not started yet. [$COUNT]" >> /init/setup.log
  fi

If the result of curl is 200, create / init / done and execute /tmp/init.cypher with the cypher-shell command. If it is not 200, do nothing and retry.

  COUNT=$(expr $COUNT + 1)
  sleep 10s

Count up and sleep for 10 seconds. By the way, ((COUNT ++)) was not available for counting up in Neo4j images.

init.cypher

MATCH (n) return n;

Initial setup Cypher. Here, all node acquisition is written as a sample, but in reality, a CREATE statement etc. is written.

If this init.sh is executed successfully, the following log will be output to setup.log under / init (volumes / neo4j / init), and a done file should be generated as well.

setup.log


The neo4j service has not started yet. [1]
The neo4j service has not started yet. [2]
The neo4j service has not started yet. [3]
The initialization process is complete.

Recommended Posts

Docker-compose deploying Neo4j with APOC
Error deploying rails5 + Mysql to heroku with Docker-compose
Start k3s with docker-compose
Run batch with docker-compose with Java batch
Precautions when creating PostgreSQL with docker-compose
Create Laravel environment with Docker (docker-compose)
DB error on deploying with Heroku
Container does not start with docker-compose