-1

I'm new to Docker.

I have a SQLite database inside a container which has been modified and i want to preserve the data for new containers.

I've tried creating commiting my container into a new image, but it didn't seems to copy the edited file, plus i've been told this is a bad practice:

docker commit 5a8f89adeead new-image

I have also tried to copy both the file and the folder in my host, but it is copied without my changes, as it was in the image:

docker cp 5a8f89adeead:/anope/data/. .

and

docker cp 5a8f89adeead:/anope/data/anope.db anope.db

What i'm doing wrong/missing here?

note: i'm currently not using a Dockerfile, but creating containers from docker hub images.

Thanks!

emboole
  • 501
  • 6
  • 23

1 Answers1

1

You generally keep data files like this outside a container. In the case of SQLite, it's a single file, so it's fairly easy to manage.

When you start the container, bind-mount a host directory into the container's data directory. Whatever's in this directory will hide what was initially in the image. If you automatically run database migrations at startup, this will also create the SQLite database file.

docker run -v $PWD/data:/anope/data ...

Now, the database is a file on the host, and you can manage that however you'd want to.

# Stop the original container (avoids integrity issues with the database file)
docker stop first-container; docker rm first-container

# Create two extra copies of the database file
mkdir data2 data3
cp data/anope.db data2
cp data/anope.db data3

# Launch two new containers, pointing at those data directories
docker run -v $PWD/data2:/anope/data --name second-container ...
docker run -v $PWD/data3:/anope/data --name third-container ...

You do not need any special support in your Dockerfile for this to work, beyond ensuring that the application code and data are not in the same directory.

Note that this setup doesn't care at all about what's in the container filesystem. We ruthlessly discarded the first container filesystem, and launched two more containers in parallel. The actual data that needs to be persisted is always kept outside the container. (I have not used docker commit, docker exec, docker cp, or docker start at all.)

If you did want to create an image with seed data, it would be very straightforward to write a Dockerfile that did that:

FROM the-same-image-you-were-running
COPY anope.db /anope/data

However, note that any sort of mount will hide the data in the image and replace it with what was mounted, with one special case around the first use of named volumes in Docker specifically. Also note that, if the directory is declared as a VOLUME (possibly in the base image), then you cannot make further changes to that directory and have them persisted.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • When I tried to copy the modified file from the container it came empty instead of my modified version. Finally I copied it with cat as follows: `$ docker exec cfb4f1f6cb96 cat /anope/data/anope.db > anope.db`. Now, regarding `docker run -v $PWD/data2:/anope/data --name second-container` would it be a bind mount? Is it preferable for data to use bind mounts instead of volumes ?. If a volume is better, is it possible to copy my file to it? thanks for your time! – emboole Oct 12 '21 at 16:54
  • 1
    If workflows like this make using the host filesystem substantially easier, using a bind mount is fine. The Docker documentation is very enthusiastic about named volumes but they do introduce real operational problems if for whatever reason you need to directly access their content. – David Maze Oct 12 '21 at 17:34