MariaDB is the community fork of MySQL and a drop-in replacement for many MySQL use cases — same wire protocol, same SQL surface for most queries, similar client tools. Running it in Docker is the same shape as running MySQL: one command for the basic case, plus a named volume for persistence so your data doesn't vanish with the container.
How do I run MariaDB in Docker?
docker run -d --name mariadb \
-e MARIADB_ROOT_PASSWORD=change-me \
-p 3306:3306 \
-v mariadb-data:/var/lib/mysql \
mariadb:11.4MariaDB 11.4 LTS in the background, root password set, port 3306 published, and a named volume on /var/lib/mysql so the data survives. (Yes, the volume path is /var/lib/mysql — MariaDB inherits the MySQL data-directory convention.)
Configure the version, ports, password, and volume.
Pick a version
mariadb:11.4— MariaDB 11.4 LTS. Released May 2024, supported through May 2029. The default for new projects.mariadb:10.11— 10.11 LTS, supported through February 2028. Still common in production.mariadb:10.6— older LTS, supported through July 2026. Use only for matching existing infrastructure.
Tags also exist for non-LTS releases (mariadb:11.5, etc.) — short support windows, useful only if you specifically need a feature in those.
The basic run command
docker run -d --name :container_name \
-e MARIADB_ROOT_PASSWORD=:root_password \
-p :host_port:3306 \
-v :volume:/var/lib/mysql \
mariadb::mariadb_versionOptional init env vars (only honored on first run, when the data directory is empty):
docker run -d --name :container_name \
-e MARIADB_ROOT_PASSWORD=:root_password \
-e MARIADB_DATABASE=myapp \
-e MARIADB_USER=appuser \
-e MARIADB_PASSWORD=apppass \
-p :host_port:3306 \
-v :volume:/var/lib/mysql \
mariadb::mariadb_versionMARIADB_* vs MYSQL_* env vars
The MariaDB image accepts both MARIADB_* and MYSQL_* env vars for compatibility with apps and Compose files that originally targeted MySQL. So all of these work:
-e MARIADB_ROOT_PASSWORD=...
-e MYSQL_ROOT_PASSWORD=... # equivalent
-e MARIADB_DATABASE=myapp
-e MYSQL_DATABASE=myapp # equivalentIf both are set, the MARIADB_* variant wins. New code should use MARIADB_*; the MYSQL_* aliases exist for "switching the image from mysql to mariadb without rewriting our Compose file."
Why you need a volume
Same reason as MySQL: the container's writable layer is destroyed when the container is removed. The data directory at /var/lib/mysql lives in that writable layer unless you mount a volume there. With -v :volume:/var/lib/mysql, the data lives in Docker-managed storage and survives container removal.
# Stop and remove the container
docker stop :container_name && docker rm :container_name
# Start a new MariaDB against the same volume — your data is still there
docker run -d --name :container_name \
-e MARIADB_ROOT_PASSWORD=:root_password \
-p :host_port:3306 \
-v :volume:/var/lib/mysql \
mariadb::mariadb_versionBind-mount alternative if you want the bytes at a specific host path:
mkdir -p ~/docker-data/mariadb
docker run -d --name :container_name \
-e MARIADB_ROOT_PASSWORD=:root_password \
-p :host_port:3306 \
-v ~/docker-data/mariadb:/var/lib/mysql \
mariadb::mariadb_versionTrade-offs are the same as MySQL: named volume is easier and avoids permission flips; bind mount is convenient for host-side backup tooling. Full breakdown in Docker Volumes vs Bind Mounts.
Practical usage: connecting
From the host (with mariadb or mysql CLI installed):
mariadb -h 127.0.0.1 -P :host_port -u root -p
# or
mysql -h 127.0.0.1 -P :host_port -u root -pThrough the container's own CLI without installing one on the host:
docker exec -it :container_name mariadb -u root -pConnection string for an app on the host:
mysql://root:change-me@127.0.0.1::host_port/myapp
(Most drivers still call it mysql:// even when talking to MariaDB — the wire protocol is the same.)
Switching from MySQL to MariaDB (or back)
A common scenario: you have a MySQL container with a volume full of data, and you want to switch the image to MariaDB. You usually can't reuse the same volume — MySQL's mysql system schema and MariaDB's diverge enough that pointing one at the other's data directory ends in a corrupted server or refusal to start. The safe procedure is:
# Dump from MySQL
docker exec mysql-container \
mysqldump -u root -p"$ROOT_PW" --single-transaction --all-databases > dump.sql
# Stop the old container
docker stop mysql-container && docker rm mysql-container
# Start MariaDB with a FRESH volume
docker run -d --name mariadb \
-e MARIADB_ROOT_PASSWORD="$ROOT_PW" \
-p 3306:3306 \
-v mariadb-data:/var/lib/mysql \
mariadb:11.4
# Wait for MariaDB to be ready, then import
docker exec -i mariadb mariadb -u root -p"$ROOT_PW" < dump.sqlSame shape in the other direction (MariaDB → MySQL). Always dump-and-restore across the two products; don't share a data directory.
Backups
# Logical backup with mariadb-dump (mariadb-dump is the modern name; mysqldump still works)
docker exec :container_name \
mariadb-dump -u root -p:root_password --single-transaction --all-databases \
> backup-$(date +%Y%m%d).sqlVolume-level snapshot (requires stopping the container for consistency):
docker stop :container_name
docker run --rm -v :volume:/source:ro -v "$(pwd):/backup" alpine \
tar czf /backup/mariadb-data-$(date +%Y%m%d).tar.gz -C /source .
docker start :container_nameDocker Compose version
services:
db:
image: mariadb::mariadb_version
environment:
MARIADB_ROOT_PASSWORD: :root_password
MARIADB_DATABASE: myapp
MARIADB_USER: appuser
MARIADB_PASSWORD: apppass
ports:
- "::host_port:3306"
volumes:
- :volume:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
volumes:
:volume:The image ships its own healthcheck.sh for the readiness check.
Common pitfalls
- Reusing a MySQL volume with MariaDB. Don't. Dump and restore.
- Init env vars ignored on second run. Same gotcha as MySQL —
MARIADB_DATABASEonly fires on first init of an empty volume. To re-init, remove the volume. - Port 3306 conflict. Pick a different host port if you already have something on 3306.
- Old MySQL clients connecting to MariaDB. Usually fine, but check if you hit auth-plugin issues — MariaDB defaults to
mysql_native_passwordfor compatibility, which makes it easier for legacy clients than MySQL 8.0+'scaching_sha2_password. - Slow first start. MariaDB initializes the data directory on first run; takes 10-30 seconds depending on the host. Check
docker logs :container_nameif it seems stuck.
What to do next
- Run MySQL in Docker — the MySQL equivalent of this article.
- Run Adminer in Docker — a lightweight GUI to talk to this MariaDB.
- Docker Volumes vs Bind Mounts — the full persistence picture.
- How to Migrate from MySQL to MariaDB — the schema-level migration article.
FAQ
Sources
Authoritative references this article was fact-checked against.
- Official MariaDB image — Docker Hubhub.docker.com
- MariaDB — about (release support policy)mariadb.org

