Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
673 views
in Technique[技术] by (71.8m points)

database - MySQL Docker container is not saving data to new image

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...