Skip to content

Repository files navigation

galeriadb

Docker image for MariaDB + Galera Cluster. Designed for Compose and Swarm, supports arbitrary node startup order, and exposes an HTTP health check for HAProxy.

Image

  • Docker Hub: galeriadb/12.1
  • Tag: latest (image name encodes MariaDB version, e.g. galeriadb/12.1:latest)

Branch main tracks MariaDB 12.1. Older versions are available in versioned branches (e.g. 11.8 for MariaDB 11.8).

Features

  • Cluster discovery from GALERIA_PEERS with bootstrap candidate logic.
  • HAProxy-friendly health check on port 9200 (Synced + wsrep_ready=ON).
  • Hot backups to S3 with optional retention and cron scheduling.
  • Restore (clone) from S3 when the data directory is empty.

Quick start

From the example Compose stack:

cd examples/docker-compose
docker compose up -d

Connect via HAProxy on port 3306:

mariadb -h 127.0.0.1 -P 3306 -u root -psecret

Configuration

Required

The container exits immediately if any required variable is missing or empty.

Variable Description Example
GALERIA_PEERS Comma-separated peer list. Use Compose service names, Swarm task names (tasks.galera), or IPs/hostnames. galera1,galera2,galera3 / tasks.galera / 10.0.0.1,10.0.0.2
GALERIA_ROOT_PASSWORD Password for MariaDB root user (no default). secret
GALERIA_BOOTSTRAP_CANDIDATE Hostname of the node that may bootstrap a new cluster when none is found. Must match one of your node hostnames. galera1

Cluster and discovery

Variable Description Default
GALERIA_CLUSTER_NAME Galera cluster name (wsrep_cluster_name). galera_cluster
GALERIA_DISCOVERY_TIMEOUT Total seconds to resolve peers before continuing. 5
GALERIA_DISCOVERY_INTERVAL Seconds between resolution attempts. 1
GALERIA_JOIN_PRIMARY_TIMEOUT For non-candidates without an initial Synced peer: seconds to pre-check for a reachable Synced peer before exit (for orchestrator restart). 30
GALERIA_READY_TIMEOUT Seconds to wait for MariaDB to accept connections before the container gives up. Time spent in a state transfer (SST) does not count against it. 60
GALERIA_SST_TIMEOUT Maximum seconds to wait while a state transfer (SST) is running. 0 waits without a limit. 3600
GALERIA_MARIADB_LOGS MariaDB/Galera server logs to container stdout/stderr. Set to on to enable; any other value keeps only entrypoint/script logs in docker logs. off
GALERIA_NODE_ADDRESS Override this node's IP address if auto-detection is wrong. auto-detected

Discovery behavior:

  • The image resolves GALERIA_PEERS and looks for a Synced node.
  • If a Synced node is found, this node joins it.
  • If none is found within the discovery window, only the bootstrap candidate starts a new cluster.
  • Non-candidates run a pre-check for up to GALERIA_JOIN_PRIMARY_TIMEOUT; if no Synced peer appears, they exit so the orchestrator can restart later.
  • In Swarm or Kubernetes, peer DNS may be empty during the first task start. The discovery window avoids long waits while still allowing late joiners.

State transfer (SST):

  • A joining node refuses client connections for as long as its state transfer takes, so the GALERIA_READY_TIMEOUT countdown is paused while a transfer is running and restarts once it finishes. A joiner is never killed mid-SST because its dataset is large or the link is slow (which would also abort the transfer on the donor).
  • The transfer itself is bounded by GALERIA_SST_TIMEOUT. Raise it (or set 0) for datasets that need more than an hour to transfer.

Health check

The image starts an HTTP listener on port 9200 with two endpoints:

Endpoint Meaning Use for
GET / Readiness: 200 only when the node is Synced and wsrep_ready=ON. Load balancers (HAProxy http-check send meth GET uri /).
GET /liveness Liveness: 200 while the node is Synced or taking part in a state transfer (receiving it as a joiner, serving it as a donor, applying the backlog afterwards). Container health checks, orchestrator probes.

The image HEALTHCHECK uses /liveness, because a node that is merely "not ready" must not be restarted: a joiner restarted mid-SST loses the transfer and also breaks it on the donor. Do not override the health check with a plain server ping (mariadb -e "SHOW STATUS ...") — a joiner has no server to answer it while its state transfer runs, so Swarm would restart the task in the middle of the transfer.

In Kubernetes, map the endpoints directly: /liveness for livenessProbe, / for readinessProbe.

The check keeps the default start period of 60s, which covers cluster connect and data directory initialization before a transfer begins. A node that restarts with a very large gcache backlog to replay (IST, with no transfer helper running and the server not yet accepting connections) can need longer; raise the health check start_period for that deployment if so.

Optional:

Variable Description Default
GALERIA_HEALTHCHECK_USER MySQL user for health check queries. root
GALERIA_HEALTHCHECK_PASSWORD Password for health check user. GALERIA_ROOT_PASSWORD

If both GALERIA_HEALTHCHECK_USER and GALERIA_HEALTHCHECK_PASSWORD are set and the user is not root, the entrypoint will create/update that user and grant the minimal permissions required for the check.

Backups to S3

Hot backups run only on nodes in Synced state.

Variable Description Default
GALERIA_BACKUP_SCHEDULE Cron schedule for backups. Empty disables cron. empty
GALERIA_BACKUP_S3_URI Full S3 URI for backups (overrides bucket+path).
GALERIA_BACKUP_S3_BUCKET S3 bucket name.
GALERIA_BACKUP_S3_PATH Path under bucket if using GALERIA_BACKUP_S3_BUCKET. mariadb
GALERIA_BACKUP_TMPDIR Temporary directory for backups. /tmp
GALERIA_BACKUP_RETENTION_DAYS Delete backups older than this many days (by S3 LastModified).
GALERIA_BACKUP_RETENTION_CUTOFF_OVERRIDE Override retention cutoff date (YYYY-MM-DD). Useful for tests.
GALERIA_CRONTAB Additional cron lines to install alongside backups.
AWS_ACCESS_KEY_ID AWS access key (optional if using IAM role).
AWS_SECRET_ACCESS_KEY AWS secret key.
AWS_REGION / AWS_DEFAULT_REGION AWS region for S3.
AWS_ENDPOINT_URL Custom S3 endpoint (e.g. MinIO).

Manual backup:

docker exec <container> /usr/local/bin/galera-backup.sh

Backup logs are written to /var/log/galera-backup.log inside the container.

Restore (clone) from S3

Restore runs only when /var/lib/mysql is empty on container startup and clone variables are set.

Variable Description Default
GALERIA_CLONE_BACKUP_S3_URI Full S3 URI for restore (overrides bucket+path).
GALERIA_CLONE_BACKUP_S3_BUCKET S3 bucket name.
GALERIA_CLONE_BACKUP_S3_PATH Path under bucket if using GALERIA_CLONE_BACKUP_S3_BUCKET. mariadb
GALERIA_CLONE_FROM Object key relative to base path or full s3:// URI. If unset, the latest backup under {hostname}/ is used.
GALERIA_CLONE_TMPDIR Temporary directory for restore files. /tmp
CLONE_AWS_ACCESS_KEY_ID AWS access key for restore.
CLONE_AWS_SECRET_ACCESS_KEY AWS secret key for restore.
CLONE_AWS_REGION / CLONE_AWS_DEFAULT_REGION AWS region for restore.
CLONE_AWS_ENDPOINT_URL Custom S3 endpoint (e.g. MinIO).

Behavior notes

  • root@% is created on startup and granted full privileges.
  • If the node is the bootstrap candidate, safe_to_bootstrap is set to 1 in grastate.dat when needed.
  • If the data directory was created by an older MariaDB version, the container runs mariadb-upgrade on startup.

Auto-migration

When a version upgrade is detected, the entrypoint runs mariadb-upgrade automatically. If S3 backup settings are configured, a hot backup is taken and uploaded before the migration runs. If backup is configured but the pre-upgrade backup fails or the node does not reach Synced within the timeout, the container exits and migration is not performed.

Optional:

Variable Description Default
GALERIA_AUTO_MIGRATE_SYNC_TIMEOUT Seconds to wait for Synced + wsrep_ready=ON before taking the pre-upgrade backup. 120

Ports

  • 3306 - MariaDB clients
  • 4567 - Galera replication
  • 4568 - IST
  • 4444 - SST
  • 9200 - HTTP health check

Build

docker build -t galeriadb/12.1:latest -f docker/Dockerfile docker/

Tests

Single entry point:

make ci

Run inside the dev container (no local toolchain required):

make ci-docker

make ci-docker runs make ci from sources baked into the dev image at /workspace and uses Docker socket passthrough (/var/run/docker.sock or path from DOCKER_HOST=unix://...).
Diagnostics from /workspace/artifacts are copied back to local ./artifacts/ after the run.

Targets:

Command Description
make ci lint, build, CST, security, smoke, deploy, backup-s3
make ci-docker same as make ci inside dev container
make lint hadolint, shellcheck, shfmt
make build build image (galeriadb/12.1:local)
make cst Container Structure Tests
make security Trivy rootfs scan (CRITICAL) + Dockle image scan
make smoke required env validation, single-node startup, graceful shutdown, Docker HEALTHCHECK
make deploy 3-node Galera + HAProxy scenarios
make backup-s3 S3 backup tests (MinIO)
make swarm Swarm sanity (run after make ci)

Tests live in tests/00.* through tests/05.*. Each test directory has its own entrypoint.sh. Diagnostics are written to ./artifacts/ on failure.

CI and publishing

GitHub Actions runs make ci in a dev container on pull requests to the main branch and on manual runs. The Swarm job runs on the same triggers after CI passes (unless [skip-ci] is set).

Images are built and published via .github/workflows/docker-publish.yml on push to main and on manual runs (skips when [skip-ci] is in the head commit message). Required secrets: DOCKER_USERNAME, DOCKER_PASSWORD.

Repository layout

  • docker/ - Dockerfile, entrypoint, entrypoint stages, backup/clone scripts, templates.
  • tests/ - CI and local test suite.
  • examples/docker-compose/ - local Compose stack (3 nodes + HAProxy).
  • examples/docker-swarm/ - Swarm stack and docs.

License

This repository is licensed under the MIT License. The image includes third-party software (MariaDB, Galera, socat, etc.) under their own licenses; see NOTICE for details.

About

Docker image for MariaDB + Galera Cluster

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Used by

Contributors

Languages