1

I am trying to create a docker image from a mysql container. The problem is that db of the new image is clean, but files/folders, which I create manually in the origin container before commit, are copied.

base mysql image is official 5.6

docker is 1.11.

I checked that folder /var/lib/mysql/d1 appears when a db is created but new image doesn't persist this folder, though folders in / root are persisted.

2 Answers 2

4

Several things happening here:

First, docker commit is a code smell. It tends to be used by those creating images with a manual process, rather than automating their builds with a Dockerfile that would allow for easy recreation. If at all possible, I recommend you transition to a Dockerfile for your image creation.

Next, a docker commit will not capture changes made to a volume. And this same issue occurs if you try to update a volume with a RUN step in a Dockerfile. Both of these capture changes to the container filesystem and store those changes as a layer in the docker image, and the volumes are not part of the container filesystem. This is also visible if you run docker diff against a container. In this case, the upstream image has defined the volume in their Dockerfile:

VOLUME /var/lib/mysql

And docker does not have a command to undo a created volume from the Dockerfile. You would need to either directly modify the image definition from outside of docker (not recommended) or build your own upstream image with that step removed (recommended).

What the mysql image does provide is the ability to inject your own database creation scripts in /docker-entrypoint-initdb.d, which you can add with your own image that extends mysql, or mount as a volume. This is where you would inject your schema, or initialize from a known backup for development.

Lastly, if the goal is to have persistence, you should store your data in a volume, not by committing containers:

docker run -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql

The volume allows you to recreate the container, upgrade to a newer version of mysql when patches are released (e.g. security fixes) without losing your data.

To backup the volume this will export to a tgz:

docker run --rm -v mysql-data:/source busybox tar -cC /source . >backup.tgz

And to restore a volume, this creates one from a tgz:

docker run --rm -i -v mysql-data:/target busybox tar -xC /target <backup.tgz
Sign up to request clarification or add additional context in comments.

4 Comments

This solution doesn't feet. I need to copy existing container and having extra file for data is too complicated. The container has short life time. I see the problem is due "volume directive" in the base image. Is there way to disable it through docker file?
I don't believe there is any way to disable a volume in a Dockerfile once it has been created in a parent image. You may be able to export and import a flat image that loses the entire base image configuration.
More of a lecture than an answer. Is it actually possible to persist data inside a container if one feels like it--or there's actually a good reason to?
@cloudsurfin No. Once the volume has been defined, the data is being persisted outside of the container. Since containers are ephemeral this is a good behavior for persistence.
0

You can make data persist by using docker commit command like below.

docker commit CONTAINER_ID REPOSITORY:TAG

docker commit | Docker Documentation

But just as BMitch's answer said, a docker commit will not capture changes made to a volume.

And usually you should use a volume to store data permanently and let a container be ephemeral without data being stored in itself.

So I guess many people think that trying to persist data without using a volume is a bad practice.

But there are some cases you might consider committing and freeze data into an image.

For example, it's handy when you have an image with all the tables and records in it if you use the image for automated test in CI. In the case of github actions, only thing you need to do is just pull the image and create the database container and run tests against the database. No need to think about migration of data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.