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.4→BaseX124.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
basexuser. - The database directory is declared as a volume so that your data survives container restarts.
- The
HEALTHCHECKrequests the start page, which is served without authentication. After three consecutive failures (roughly 30 seconds), the container is marked asunhealthy.
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.