VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Quick Start
Environment Variables
MYSQL_USER and MYSQL_PASSWORD must be set together. The created user receives full access to MYSQL_DATABASE.
Persistent Data with Volumes
Without a volume, all data is lost when the container is removed. Mount a volume to persist the data directory:mysql-data) persists across container restarts and removals. To use a host directory instead:
Choosing an Image and Volume Strategy
For most workloads, named volumes are the right default. Bind mounts are useful when you need to inspect or edit the data directory directly from the host, but the performance cost matters on macOS and Windows.
Docker Compose
For development environments with multiple services, Docker Compose is the standard approach:healthcheck with depends_on: condition: service_healthy ensures the application container doesn’t start until MySQL is ready to accept connections — not just started.
Custom Configuration
Pass a custommy.cnf by mounting it:
Initialization Scripts
The container runs any.sql or .sh files placed in /docker-entrypoint-initdb.d/ on first startup (when the data directory is empty):
Connecting from Applications
Inside a Docker Compose network, containers connect to MySQL by service name:127.0.0.1 (not localhost — MySQL’s socket isn’t available on the host):
When to Run MySQL in Docker
Production Considerations
Docker works well for MySQL in production with a few caveats:- Data persistence: Use named volumes or bind mounts. Never let MySQL data live in the container layer.
- Memory limits: Set
--memoryin Docker to prevent MySQL from exhausting host memory, and tuneinnodb_buffer_pool_sizeto match. - Backups:
mysqldumpworks inside the container:docker exec mysql-dev mysqldump -u root -p myapp > backup.sql - Logging: MySQL logs go to stdout/stderr in Docker. Use
docker logs mysql-devor configure your logging driver. - Upgrades: Pull the new image tag, stop the old container, and start the new one with the same volume. MySQL’s upgrade process runs automatically on first start with a newer version.
Frequently Asked Questions
Why can’t I connect with mysql -h localhost from the host?
On Linux and macOS, localhost causes the MySQL client to try connecting via Unix socket, which isn’t available on the host. Use 127.0.0.1 explicitly: mysql -h 127.0.0.1 -P 3306.
How do I make MySQL data persist in Docker?
Mount a named volume to/var/lib/mysql when you start the container: -v mysql-data:/var/lib/mysql. Without this, all data is stored in the container’s writable layer and lost when you run docker rm. Named volumes survive container removal and are managed by Docker — use docker volume ls to list them and docker volume inspect mysql-data to find the storage location. In Docker Compose, declare the volume under the top-level volumes: key and reference it in the service’s volumes: list (the example in the Docker Compose section above shows this pattern).
How do containers in Docker Compose connect to MySQL?
Containers in the same Compose project share a default network. Your application container connects to MySQL using the service name as the hostname — if your database service is nameddb, the connection string is host=db port=3306. You don’t need to expose ports between containers; port mapping (-p 3306:3306) is only needed for connections from the host machine. Use depends_on: condition: service_healthy with a healthcheck on the MySQL service to prevent the application from starting before MySQL is ready.
How do I run a SQL file against a running container?
Troubleshooting
See also
- MySQL Replication Basics — running source/replica pairs in Docker Compose
- MySQL Backup Strategies — backing up data volumes in containerized MySQL

