MySQL still plays a large part in many software stacks and while many IaaS vendors have their own hosted versions (i.e. Amazon RDS), it’s still fairly common to run MySQL in a Docker container, especially in development environments.
One common problem that’s encountered with MySQL is initializing it before its use and having your application connect only after initialization is complete. While some find it acceptable to include initialization code in their application startup, in my own projects I prefer a run script that handles initialization as part of starting the container’s process and then have the application startup gracefully handle the connection.
Dockerfile — Installs mysql-apt-config to support fetching MySQL via apt-get, adds our support files, and compiles the timezone.sql file from the base image’s timezone files
mysql.list — Apt source list for downloading MySQL
run.sh — Run script that we’ll be using to initialize and launch MySQL
The Dockerfile shown below installs MySQL, creates the timezone SQL, and adds the remaining supporting files to the image.
The MySQL configuration file can be modified as needed. Do note the datadir location is set to /var/lib/mysql. Launching the container with a data volume mounted at /var/lib/mysql will allow you to persist data when the container is removed.
The apt sources below should be updated to match the base ubuntu image from the Dockerfile when updates occur.
The run script below should be used as the container command to start MySQL
Starting the container with “run.sh” ensures the database is initialized and that the root user has a password. Additionally, it installs the memcached plugin and populates the timezone tables. Upon completion, it launches mysqld_safe as the final command.
We can build the image:
After a few moments, the database will be fully initialized and ready to accept connections.
This works OK when you’re manually launching containers, but causes problems with Docker Compose, Elastic Beanstalk, and other platforms that launch containers for you. Our solution is rather simple.
A run script acts as a wrapper around any applications that need to access the database and requires a configurable number of successful connections before launching the application.
Here’s how we do it:
We include check_db.sh in any run scripts that we use to start our database-dependent applications like so:
Until our container is able to make 5 successful connections to our MySQL container, the uwsgi process simply won’t start and we can tweak the minimum required connection attempts as needed.
No more launch failures due to unreachable MySQL containers!
One Response to “A Better Dockerized MySQL”
Marcelo
After complete these steps, the docker run logs ‘exec user process caused “no such file or directory”‘
Marcelo
After complete these steps, the docker run logs ‘exec user process caused “no such file or directory”‘