Is Running MySQL in Docker Really a Bad Idea?
This article dissects the common claim that MySQL should not be run in Docker by explaining the underlying design mismatch, measuring I/O overhead, examining persistence and resource‑isolation pitfalls, reviewing replication challenges, and presenting real‑world cases from JD and Tongcheng to show when containerization is safe and when it isn’t.
In interviews candidates often hear the question “Why is MySQL not recommended to run in Docker?” The short answer is partially correct but incomplete: Docker’s design for stateless services conflicts with MySQL’s stateful nature, and certain scenarios introduce real risks.
What Docker Is Designed For
Docker containers provide process isolation and are ideal for stateless services such as APIs, Nginx, or job schedulers that can be destroyed and recreated without preserving data.
MySQL, by contrast, is stateful—every INSERT and transaction must be flushed to disk, and a container crash would lose that state, which fundamentally opposes Docker’s typical use case.
Issue 1: I/O Performance Degradation
Docker uses the overlay2 storage driver, a layered filesystem that adds an extra proxy layer for reads and writes. Empirical tests show that disk I/O inside a container is typically 10‑20% slower than on the host.
# Measure raw disk write speed on the host
dd if=/dev/zero of=test.bin bs=1G count=1 oflag=direct
# Same test inside a Docker container
docker run --rm -it ubuntu dd if=/dev/zero of=test.bin bs=1G count=1 oflag=directIf a bind‑mount is used instead of a named volume, the data bypasses the overlay layer and I/O loss can drop to under 1%.
Issue 2: Data Persistence Is Not Just a Volume
Mounting a volume is only the first line of defense. Three failure scenarios illustrate why additional safeguards are needed:
Accidental container removal: docker rm -f mysql leaves the volume orphaned and data becomes inaccessible.
Crash during fsync: If the container crashes while MySQL is performing fsync(), data may become corrupted; the probability of such crashes is higher in containers.
Scaling with shared data directory: MySQL’s data files use exclusive locks, so two containers cannot share the same directory; you must deploy master‑slave replication instead of simply launching multiple containers.
Issue 3: Incomplete Resource Isolation
Docker relies on Linux cgroups to set resource limits (e.g., 4 GB memory). Limits are only upper bounds; they do not guarantee that MySQL will retain resources when other containers (e.g., a memory‑leaking Spring Boot service) consume them, potentially triggering the OOM killer and killing MySQL.
Issue 4: Replication and High‑Availability Complexity
Production MySQL usually runs with master‑slave replication or HA failover. Containerizing these adds extra latency through Docker’s bridge network, IP changes on container restart break replication configs, and split‑brain scenarios can corrupt data. Kubernetes StatefulSets can mitigate these issues but require substantial configuration effort.
Real‑World Deployments
JD.com: Over 70% of its MySQL instances (more than ten thousand) run in Docker under a system called CM (Containerized MySQL). JD advises that instances larger than 1 TB or with extreme performance requirements stay on bare metal.
Tongcheng Yilong: Migrated >90% of MySQL services (over 2,000 instances) to Docker, reporting a 30× increase in resource utilization and a 70× acceleration in database delivery.
Official MySQL Docker Support
The official MySQL documentation provides Docker run scripts that bind‑mount configuration and data directories to the host, indicating that Docker is considered a production‑ready deployment method.
docker run --name=mysql1 \
--mount type=bind,src=/path-on-host/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/path-on-host/datadir,dst=/var/lib/mysql \
-d container-registry.oracle.com/mysql/community-server:tagWhen Not to Use Docker for MySQL
Avoid Docker if the dataset exceeds 1 TB, I/O pressure is high, the workload cannot tolerate performance variability, the team lacks container‑ops experience, or HA designs are not yet defined.
When Docker Is Acceptable
Docker is suitable for development and testing, for workloads with modest data size and performance requirements, and when the team has solid Docker and MySQL expertise, reliable backup, monitoring, and HA plans.
Production‑Ready Configuration Tips
# Use bind mounts to bypass overlay2 and achieve near‑native I/O
docker run -d \
--name mysql-prod \
-v /data/mysql/data:/var/lib/mysql \
-v /data/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-v /data/mysql/logs:/var/log/mysql \
--memory=8g \
--cpus=4 \
mysql:8.0Expose both data and log directories, and set memory/CPU limits to prevent a runaway MySQL process from exhausting the host.
Conclusion
The blanket statement “Do not run MySQL in Docker” was valid when container tooling and operational experience were immature. Today the recommendation should be qualified: do not run core MySQL instances in Docker unless the team is prepared with proper monitoring, backup, and HA strategies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
