Stefano Borini
Stefano Borini

Reputation: 143905

Can I create a "template volume" in docker?

I have multiple docker containers, and all of them must have a common content in a subdirectory. This common content is pretty much standard, so I would enjoy being able to package it somehow.

One option would be to create a volume, put the files in the volume, and then bind the containers to the volume, however from what I understand of docker volumes, the result would be that the volume is shared among containers. Any changes a container does to the volume's content, will appear in the other container. I don't want this.

Note that keeping it readonly is not an option. I want the data to be read-write, I simply don't want it to be shared among containers, and at the same time I don't want to keep them in the image.

Is this possible in Docker?

Upvotes: 0

Views: 883

Answers (1)

thaJeztah
thaJeztah

Reputation: 29117

As long as you don't re-use the same volume for other containers, you can use a docker image as template, and use it to "propagate" the volume data;

1. Create a directory for all your template files;

mkdir data

# just creating some dummy files here to illustrate the concept
touch data/foo data/bar data/baz data/bla data/bla2

2. Create a Dockerfile for building the template image

This image contains default data to be used for the containers to used We're using a tiny image ("hello-world") as it requires a command to allow a container to be created from it

FROM hello-world
COPY . /data/

3. Build the template image

docker build -t template-data .

4. Create a new volume, and propagate the data

Then, you can create volume, create a container from the image, and attach the volume to it. The first time the volume is used and is still empty, the files are copied from the container to the volume.

After the volume is created, and propagated, we don't really need the container anymore (the data is copied to the volume), so we're passing the --rm flag as well, so that the container (not the volume, because it's a "named" volume) is removed directly after it exits

# create an empty volume
docker volume create --name data-volume1

# start the container (which copies the data), and remove the container
docker run -it --rm -v data-volume1:/data template-data

5. Use the volume for your application

Then start your application container, and attach the volume (which now contains the template data) to it.

For this example, I just start an alpine container and show the contents of the volume, but normally this would be your application;

docker run --rm -v data-volume1:/somewhere alpine ls -l /somewhere

And you can see the data is there;

docker run --rm -v data-volume1:/somewhere alpine ls -l /somewhere
total 0
-rw-r--r--    1 root     root             0 Jun  2 20:14 bar
-rw-r--r--    1 root     root             0 Jun  2 20:14 baz
-rw-r--r--    1 root     root             0 Jun  2 20:14 bla
-rw-r--r--    1 root     root             0 Jun  2 20:14 bla2
-rw-r--r--    1 root     root             0 Jun  2 20:14 foo

You can do this multiple times, but you need to create a new volume for each project/application, otherwise they share the same volume, so are working on the same data;

docker volume create --name data-volume2
docker volume create --name data-volume3
docker volume create --name data-volume4

docker run -it --rm -v data-volume2:/data template-data
docker run -it --rm -v data-volume3:/data template-data
docker run -it --rm -v data-volume4:/data template-data

docker run --rm -v data-volume2:/somewhere alpine ls -l /somewhere
docker run --rm -v data-volume3:/somewhere alpine ls -l /somewhere
docker run --rm -v data-volume4:/somewhere alpine ls -l /somewhere

Hope this helps!

Upvotes: 2

Related Questions