Docker

This article shows how to run BaseX in a Docker container. Instead of relying on a prebuilt image, we recommend writing your own small Dockerfile. This keeps you in full control, results in a lean image, and is the most future-proof approach: it works with every past and upcoming BaseX release, and you can freely adjust it to your own needs.

We used to publish official images on Docker Hub. These images are no longer maintained (the last ones supported BaseX 9), so they should not be used anymore. The recipes below replace them.

Reference Dockerfile

The following Dockerfile downloads an official release and runs the HTTP Server. It is a multi-stage build: the first stage fetches and unpacks a release, the second stage assembles a minimal runtime image on top of a Java runtime.

# ---- Stage 1: download and unpack a BaseX release ----
FROM alpine:3 AS fetch
ARG BASEX_VERSION=12.4
RUN apk add --no-cache unzip wget \
 && ZIP="BaseX$(echo "${BASEX_VERSION}" | tr -d '.').zip" \
 && wget -q "https://files.basex.org/releases/${BASEX_VERSION}/${ZIP}" \
      -O /tmp/basex.zip \
 && unzip -q /tmp/basex.zip -d /opt

# ---- Stage 2: minimal runtime image ----
FROM eclipse-temurin:21-jre-alpine
LABEL org.opencontainers.image.source="https://basex.org" \
      org.opencontainers.image.description="BaseX XML database / XQuery server"

# 'bash' is required by the start scripts; add a non-privileged user
RUN apk add --no-cache bash \
 && addgroup -S basex && adduser -S basex -G basex

COPY --from=fetch --chown=basex:basex /opt/basex /opt/basex
COPY --chmod=755 docker-entrypoint.sh /usr/local/bin/

ENV PATH=/opt/basex/bin:$PATH
WORKDIR /opt/basex
VOLUME ["/opt/basex/data"]
USER basex

# 8080: HTTP server (REST, RESTXQ, DBA)
EXPOSE 8080

HEALTHCHECK --interval=10s --timeout=5s --start-period=15s --retries=3 \
    CMD wget -q -O /dev/null http://localhost:8080/

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["basexhttp"]

A few notes:

  • The BaseX version is passed as a build argument (BASEX_VERSION). To build a different version, override it on the command line; you don't need to edit the file. The download URL is derived from the version number (12.4BaseX124.zip).
  • Eclipse Temurin is used as a free, multi-platform Java runtime. Any distribution with Java 17 or later will do.
  • The container runs as a non-privileged basex user.
  • The database directory is declared as a volume so that your data survives container restarts.
  • The HEALTHCHECK requests the start page, which is served without authentication. After three consecutive failures (roughly 30 seconds), the container is marked as unhealthy.

Entrypoint

The entrypoint sets the admin password on the very first start (see Admin Password) and then hands over to the given command. Save it next to the Dockerfile as docker-entrypoint.sh:

#!/bin/sh
set -e

# Route the log to standard output (docker logs). Prepended, so additional
# options in $BASEX_JVM can still override it.
export BASEX_JVM="-Dorg.basex.LOG=stdout $BASEX_JVM"

# On first run, apply the admin password from $BASEX_ADMIN_PASSWORD (if provided).
# If unset, BaseX generates a random initial password and writes it to the log.
if [ -n "$BASEX_ADMIN_PASSWORD" ] && [ ! -e data/users.xml ]; then
  basex -c "PASSWORD $BASEX_ADMIN_PASSWORD"
fi

exec "$@"

Building and Running

Build the image (optionally choosing a specific BaseX version) and start a container:

# Build (use the default version, or override it)
docker build -t basex .
docker build -t basex --build-arg BASEX_VERSION=12.4 .

# Run the HTTP server
docker run -d --name basex \
  -p 8080:8080 \
  -e BASEX_ADMIN_PASSWORD=change-me \
  -v basex-data:/opt/basex/data \
  basex

The DBA, REST and RESTXQ interfaces are now available at http://localhost:8080.

Ports

Port Service
1984 Database server (client/server protocol, Clients). Only opened if basexhttp is started with -L; the port must then be exposed and published in addition.
8080 HTTP server: REST, RESTXQ and the DBA web interface.
8081 Stop port (used internally to shut down the HTTP server).

Persisting Data

BaseX stores its databases, the user registry and the repositories below the data directory (/opt/basex/data in the image). Mount a named volume or a host directory to this path to keep your data across container rebuilds:

docker run -v basex-data:/opt/basex/data ... basex

If you also want to persist installed XQuery Modules or a custom webapp directory, mount /opt/basex/repo and /opt/basex/webapp accordingly.

Admin Password

BaseX ships with a single admin user. On the first start, if no user registry exists yet, a random initial password is generated and written to the log – look for a line such as:

Initial admin password (change after first login): ...

The reference entrypoint routes the log to standard output (by setting the LOG option to stdout), so the password directly shows up in the container log:

docker logs basex        # reveals the generated initial password

To write the log to files below the data/.logs directory (i.e., onto your mounted volume) instead, override the LOG option through BASEX_JVM.

To set a known password from the outset instead, pass it via the BASEX_ADMIN_PASSWORD environment variable, as shown in the reference entrypoint. The variable is only evaluated on the first run; afterwards, manage credentials with the User Management commands or the DBA.

Configuration

The basexhttp command accepts all Command-Line Options of the HTTP server. Append them to the container command – for example, to bind the HTTP server to a different port:

docker run ... basex basexhttp -h 9090

To make the databases accessible to the client APIs, start the database server in addition with -L, and publish its port:

docker run -p 8080:8080 -p 1984:1984 ... basex basexhttp -L

JVM options (such as the maximum heap size) can be supplied through the BASEX_JVM environment variable, which is evaluated by the start scripts:

docker run -e BASEX_JVM="-Xmx2g" ... basex

Static configuration can be provided by mounting a .basex file or a custom web.xml/jetty.xml, or by passing system properties via BASEX_JVM (e.g. -Dorg.basex.CHOP=false).

Docker Compose

For a reproducible local setup, the same image can be described with Docker Compose:

services:
  basex:
    build:
      context: .
      args:
        BASEX_VERSION: "12.4"
    ports:
      - "8080:8080"   # HTTP: REST, RESTXQ, DBA
    environment:
      BASEX_ADMIN_PASSWORD: "change-me"
    volumes:
      - basex-data:/opt/basex/data
    restart: unless-stopped

volumes:
  basex-data:

Start it with docker compose up -d.

BaseX as a Base Image

Because the image already contains a Java runtime and a full BaseX installation, it doubles as a base image for your own Web Applications. Add your RESTXQ modules, static files and permissions on top:

FROM basex
COPY --chown=basex:basex webapp/ /opt/basex/webapp/

Multi-Architecture Images

The reference Dockerfile is architecture-independent: it downloads a platform-neutral release and relies on a multi-platform Java base image. You can therefore build images for several architectures at once with buildx:

docker buildx build --platform linux/amd64,linux/arm64 -t basex .

Community Images

If you prefer a ready-made, well-maintained image over building your own, have a look at the community project Quodatum/basex-docker, which publishes multi-architecture images and demonstrates a GitHub Actions workflow for automated builds.

Questions, improvements and further Docker recipes are always welcome on our mailing list.


⚡Generated with XQuery