A Productive Nine Months
It’s been around 9 months since we did the first cut of our own MySQL Docker images, and it is time for a bit of an update on where we are in Dockerland these days, and also to talk about some important security related improvements we made to the images lately.
When we started this activity, we set three goals for ourselves:
- We wanted to contribute to the amazingly popular community maintained MySQL Docker images.
- We wanted to roll our own images as well, so we could go in some new directions and implement some features that the existing community might not be that interested in.
- We wanted to take the experience from our Docker work back to our own products so we can improve the way MySQL works inside containers.
Throughout, we have made sure to work as much as possible inside the Docker community, keeping up with community image changes and contributing back any changes and improvements from our own images to the community. This has proved very fruitful, and the results so far include much better docs for both images, more robust image startup and improvements to security. More on some recent, specific improvements below.
Meanwhile, we have made a number of adjustments to MySQL that make us a better fit for containerization. An example is that MySQL 5.7 has a new
--initialize option that will create the data directory and populate the tables in the MySQL system database on initial startup. With pre-5.7 versions of MySQL Perl must be available in the container because initialization is done by a Perl script called
mysql_install_db. We have also made several changes to how MySQL behaves on startup, in order to fix both robustness and security issues on container startup … and more is on the horizon as we start development for the next major version of MySQL.
Let me say a big thank you to the Docker community who have welcomed us and been very supportive of our Docker related efforts.
Some Important Security News
I’ll go on to highlight some important improvements that we’ve made lately, and that have also recently gone into the community maintained images. Previously, the only way you could set a password for the MySQL
root admin user on initial container startup was to pass the
MYSQL_ROOT_PASSWORD environment variable on the
docker run command line. This may be fine when you are doing automated deployments using e.g. orchestration tools like Docker Compose, but if you start your container manually from the command line, giving the
root password in clear text is a security problem.
To improve security, there is now a new, strongly recommended way of starting the container manually (breaking backward compatibility is of course a no-go, so the old
MySQL_ROOT_PASSWORD way is still supported). By setting the new environment variable
yes on the
docker run command line, if desired in combination with
MYSQL_ONETIME_PASSWORD=yes, you will be able to hide the admin password from prying eyes.
Here is an example:
docker run --name my-container-name -e MYSQL_RANDOM_ROOT_PASSWORD=yes -e MYSQL_ONETIME_PASSWORD=yes -d mysql/mysql-server:tag
This starts the container
my-container-name. A strong random password gets generated on container startup, and this password gets written to
stdout inside the container, which means that it ends up in the Docker log of the container. Grab it as follows:
docker logs my-container-name
Look for the line starting with
GENERATED ROOT PASSWORD in the output, and there it is.
If you also set
MYSQL_ONETIME_PASSWORD=yes on the command line, you will need to change the password on first login. Start a
mysql client session against the MySQL instance in the container; in this example we will do this from a shell inside the container itself:
docker exec -it my-container-name bash
mysql client session and use the randomly generated
root password to log in:
mysql -u root -p
Then set a new, secure password on the
mysql client command line:
ALTER USER root IDENTIFIED BY 'my-new-pw';
As you can see, this more secure way of running your container involves a few more steps than the old one, but we strongly recommend doing it this way for any use case of importance.
Oh, and just one more thing. One of the most frequent types of request for improvements to the community images seems to be addition of
docker run environment variables that can be used to control the behaviour of MySQL. This can quite easily be accomplished through a (strangely little known) feature of the MySQL images: any options given at the end of the
docker run command line will simply be passed to the
mysqld process running inside the container. A popular example includes setting the default charset and collation for all databases in the containerized MySQL instance:
docker run --name my-container-name -d mysql/mysql-server --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
This sets the default charset and collation to full 4-byte UTF-8.
Thanks for reading. We’d be delighted to hear from you if you are a MySQL-on-Docker user, so drop us a line in the comments section below or comment on our main page on Docker Hub. And in case you should encounter any issues or have concrete feature or improvement requests: file a bug in the MySQL bug database.