I'm trying to create a MySQL Docker container that is preset with a certain schema and seed data so that I can have other containers connect to it as a db. I'm using the trusted dockerfile/mysql image as a base, and I wrote a Dockerfile to create a new image from that base and add my schema.sql into it. After building that image (mysql:base), I've been trying to run bash in new container, then go into mysql and create my database and then import the schema. I then exit the container and try to commit the container to a new Docker image. However, the resulting image does not persist any of the changes I made to the MySQL db. It does persist other files that I wrote in the container, but not the db.
Here is the Dockerfile I use to build the initial image (myorg/mysql:base).
FROM dockerfile/mysql:latest
MAINTAINER (me)
ADD schema.sql /data/schema.sql
EXPOSE 3306
# Define working directory.
WORKDIR /data
CMD ["mysqld_safe"]
After building that, I go into the image:
docker run -i -t myorg/mysql:base bash
And run MySQL to import the schema:
myslqd_safe &
141218 00:15:56 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
mysql -u root
mysql> CREATE DATABASE mydb;
exit;
mysql -u root -D mydb < schema.sql
I can go into mysql and verify the schema has been imported successfully:
mysql -u root -D mydb -e "SELECT * from tokens;"
Also, if I go into /var/lib/mysql
I can see that there is a mydb
directory that contains .frm files corresponding to the db.
But when I exit and try to commit that container to a new image:
docker commit -m="import schema.sql" -a="Me" 72c2ff39dd65 myorg/mysql:seed
And then go into the new image:
docker run -i -t --rm myorg/mysql:seed bash
The db files are no longer in /var/lib/mysql, and running mysql -u root -e "SHOW DATABASES"
does not show the mydb
database, only the default mysql
, information_schema
, and performance_schema
dbs. I found that if I created a new textfile in the container (echo 'test' > newfile
), that file would be present in the committed image, but not the db.
I wonder if this has something to do with the fact that the trusted image Dockerfile has VOLUME ["/etc/mysql", "/var/lib/mysql"]
so it mounts the db directory as a volume. My Dockerfile does not have this command, but I don't know if it's inherited anyway (I don't really understand how volumes work well enough to know how this might affect my build). I don't need the db mounted as a volume because I need another container to connect to it over a network connection (I'm going to use docker links for that).
FWIW, I am running boot2docker 1.3.2 on OS X 10.9.5.
Hence, if you want the changes to persist, you can use the Docker commit command. The commit command will save any changes you make to the container and create a new image layer on top of it.
As another answer and you have stated volumes cannot be committed and child containers do in fact inherit volume definitions from parents. Hence any changes to the volume will be discarded. I would like to add data such as mysql database files should always be in volumes for several reasons and you should not be trying to commit it into your image.
So what should you do instead?
You are probably better off rolling your own mysql. That way there are no surprises, no hidden "magic" in there.
If you look at an example dockerfile for mysql core, you can see the VOLUME declaration for /var/lib/mysql.
Docs on docker volumes.
Data volumes
A data volume is a specially-designated directory within one or more containers that bypasses the Union File System to provide several useful features for persistent or shared data:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With