Experimenting eXist-DB on Docker

I’ve been using eXist-DB for some time for the project of the Dicion├írio da Academia de Ci├¬ncias de Lisboa, that is being revived from the PDF into TEI, so that a new digital version can be soon released.

Recently I needed to update the server where eXist-DB was running, and decided to use a dockerized version of it. Although that can make things a little slower (not really sure), it makes things easier to replicate, and now I can have, easily, the dictionary database running on my laptop or in the server, using the same code.

I am using the default latest version of eXist-DB docker image. The only difference is that, because my XQuery code uses FunctX functions, I needed to import that module. Thus, my Dockerfile is composed by:

FROM existdb/existdb:latest

ADD http://exist-db.org/exist/apps/public-repo/public/functx-1.0.1.xar /exist/autodeploy

I have the data and application on a GIT repository, as exported by the eXist-DB backup tool. Thus, I decided to create a simple script to import the data, instead o creating the docker image already with that data. Therefore, my docker-compose.yml file is composed by:

version: '3.3'
services:
  exist:
    build: ./dacl/docker
    container_name: exist
    ports:
        - 8080:8080
        - 8443:8443
    volumes:
        - ./data:/exist/data
        - ./config:/exist/config
        - ./dacl:/import
        - ./outdir:/export

The relevant parts:

  • The path to the folder including the Dockerfile (dacl/docker)
  • Ports 8080 and 8443 are used by eXist-DB, and I am just forwarding them to the host
  • Created four volumes: data stores the binary database data, config stores the configuration files, and import and export volumes are used to import data, and export data for backup.

For importing all data into the database I am using a shell script. The first five lines import some collections. The last two execute two auxiliary scripts, the first to re-index application data, and the second to create the proper groups, users and assign passwords.

First, the import.sh script is:

#!/usr/bin/env bash

docker-compose exec -T exist java org.exist.start.Main backup -u admin -r /import/db/academia/__contents__.xml
docker-compose exec -T exist java org.exist.start.Main backup -u admin -r /import/db/apps/academia/__contents__.xml

docker-compose exec -T exist java org.exist.start.Main backup -u admin -r /import/db/academia-2001/__contents__.xml
docker-compose exec -T exist java org.exist.start.Main backup -u admin -r /import/db/apps/academia-2001/__contents__.xml

docker-compose exec -T exist java org.exist.start.Main backup -u admin -r /import/db/schemas/__contents__.xml

docker-compose exec -T exist java org.exist.start.Main client -u admin -F /import/xq/repair.xq
docker-compose exec -T exist java org.exist.start.Main client -u admin -F /import/xq/users.xq

Note that the XQuery scripts are being held in the same folder that is mounted in the import volume. Otherwise, you will not be able to access it from inside the container.

The repair XQuery script holds this code:

import module namespace repair="http://exist-db.org/xquery/repo/repair"
at "resource:org/exist/xquery/modules/expathrepo/repair.xql";
repair:clean-all(),
repair:repair()

And finally, the users Xquery script has the following code:

sm:passwd('admin','admin-password),
sm:create-group('dacl'),
sm:create-account('ana','ana-password','dacl'),
sm:chgrp(xs:anyURI('/db/academia'), 'dacl'),
sm:chgrp(xs:anyURI('/db/academia-2001'), 'dacl'),
sm:chgrp(xs:anyURI('/db/apps/academia-2001'), 'dacl'),
sm:chgrp(xs:anyURI('/db/apps/academia'), 'dacl'),
sm:chmod(xs:anyURI('/db/academia-2001'), 'rwxrwx---'),
sm:chmod(xs:anyURI('/db/academia'), 'rwxrwx---'),
sm:chmod(xs:anyURI('/db/apps/academia-2001'), 'rwxrwx---'),
sm:chmod(xs:anyURI('/db/apps/academia'), 'rwxrwx---')

Also, in case it gets useful, this is my backup.sh script

docker-compose exec -T exist java org.exist.start.Main backup -u admin -p admin.entrada -b /db/academia -d /export
docker-compose exec -T exist java org.exist.start.Main backup -u admin -p admin.entrada -b /db/academia-2001 -d /export
docker-compose exec -T exist java org.exist.start.Main backup -u admin -p admin.entrada -b /db/apps/academia -d /export
docker-compose exec -T exist java org.exist.start.Main backup -u admin -p admin.entrada -b /db/apps/academia-2001 -d /export
docker-compose exec -T exist java org.exist.start.Main backup -u admin -p admin.entrada -b /db/schemas -d /export

rsync -aASPvz --delete-after outdir/db/ dacl/db/

DATE=`date +%Y%m%d`
cd dacl && git commit -a -m "Backup $DATE" && git push origin v5

Of course this is not rocket science, and this approach might have a lot of problems, but in the other hand, it might get handy to someone.