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 containerdocker stop :container_name && docker rm :container_nameStart a new MariaDB against the same volume, your data is still theredocker 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 -pormysql -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
Mostly. The wire protocol and most SQL are compatible. The image even accepts MYSQL_* env vars for app/Compose compatibility. The differences show up at the edges: some MySQL 8.x features aren't in MariaDB, some MariaDB features aren't in MySQL, and the system schemas diverge. For greenfield projects either works; for migration, dump-and-restore is safer than data-directory swap.
Yes. The MariaDB image accepts both, and either works for setting the root password on first init. New projects should use MARIADB_*; the MYSQL_* aliases exist for switching images without rewriting Compose files.
mariadb:11 is a moving alias to the latest 11.x release (currently 11.4 LTS, will move to 11.5 etc. as they release). mariadb:11.4 pins to the 11.4 LTS line specifically. For production, pin to the LTS line (11.4 or 10.11); for evaluation, the moving major-version alias is fine.
On Linux: /var/lib/docker/volumes/<volume-name>/_data. On Mac and Windows, inside Docker Desktop's virtual disk, not a host path you can cd to directly. See Where Are Docker's Files on a Mac?.
Yes, different host ports. -p 3306:3306 for MySQL, -p 3307:3306 for MariaDB, or any pair of free host ports. Different containers, different volumes, no conflict.
Sources
Authoritative references this article was fact-checked against.
- Official MariaDB image, Docker Hubhub.docker.com
- MariaDB, about (release support policy)mariadb.org





