11

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.

Taylor H
  • 161
  • 2
  • 3
  • 10

2 Answers2

4

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.

  1. If you have to migrate containers there is no easy way to extract data from containers if its not in a volume.
  2. If you want to start multiple containers that share data you have to have data in a volume.
  3. If you want to change your container definition with say new volumes or ports you have to delete and recreate it. If you have data in the container you will loose it. (See this question for an example of this case.)
  4. The union file system is slower than normal file systems which will slow down your application or database.

So what should you do instead?

  1. Use a data only container that can be linked with any instance of the service container. Then you can use volumes-from to get your data into the service container.
  2. Use a host mounted volume so that you can restart containers and mount the same location into new containers.
Community
  • 1
  • 1
Usman Ismail
  • 17,999
  • 14
  • 83
  • 165
  • I give you +1 especially for reason 4 which is too often ignored. Never put data in the Union filesystem – Thomasleveil Dec 21 '14 at 20:58
  • Apparently with Docker 1.9.0 and the new volume api (https://docs.docker.com/engine/reference/commandline/volume_create/) there is no need to use data only containers anymore. Do you know if this could be applicable to this question? – lloiacono Jan 11 '18 at 11:18
2

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:

  • Data volumes can be shared and reused between containers
  • Changes to a data volume are made directly
  • Changes to a data volume will not be included when you update an image
  • Volumes persist until no containers use them
user2105103
  • 11,599
  • 2
  • 18
  • 11
  • Well I guess that answers why it wasn't saving. I had initially tried to roll my own mysql container but found it too difficult to set up and configure properly. Is there another prebuilt image that might be better suited to my purpose? – Taylor H Dec 19 '14 at 20:21
  • 4
    Plus 1 for identifying the issue but minus 1 for "Roll your own." You do not need to repeat work that has already been done. – Usman Ismail Dec 19 '14 at 20:21
  • Perhaps do not need to, but at least you own it/understand it. – user2105103 Dec 19 '14 at 21:05
  • "Roll your own" can save you time though particularly when it concerns obscure and undocumented behavior that would otherwise lead you 10 hours down a rabbit hole. +1 – Coder Guy Sep 25 '18 at 17:48
  • As long as everyone knows you shouldn't do this, linked page has a very simple 3 line Dockerfile that just takes the base MySQL image, creates a new data directory that is not a VOLUME, and then adds command line options to CMD to use that data directory. After that docker commit works as expected. https://web.archive.org/web/20220602202900/https://www.elephdev.com/index.php/cDocker/186.html?ref=addtabs&lang=en – John C Earls Jun 02 '22 at 20:31