On data-only containers in Docker…

Sometime you just need a place to dump things…


What’s the problem?

You might read that using scratch is a bad idea for the data-only container pattern and maybe it’s true. Maybe you should use another copy of your base image to host the data. But doesn’t that break the concept of a data-only container? As a security-minded individual this strikes me as somewhat unusual to store applications with data if the point is to segregate the two. So I set out to prove that using a secure data container pattern is possible — in as few commands as possible.

Big warning

This method is a little unusual as it requires an “initialization phase” for the data container. Although understandable, it’s not perfect and may not scale well without further work.

How it’s done

Suppose you start with a Dockerfile like so…

FROM alpine
RUN adduser -D test && mkdir /foo && touch /foo/bar && chown -R test:test /foo
USER test
CMD ls -lh /foo

And you build it thusly:

docker build -t test -< Dockerfile

Let’s run this container without a data container:

docker run --rm test

Which delivers this fully expected news:

total 0
-rw-r--r--    1 test     test           0 Apr  1 12:23 bar

And you create a dummy data container from scratch:

docker create -v /foo --name test-data scratch foo

Obviously since there are no applications foo would never run, but since this is a data container that’s not a problem as we will never start it.

Now let’s run the image with our shiny new data container.

docker run --rm --volumes-from test-data test


total 0

Drat. Right, there’s nothing in that folder now because the data container is empty. Let’s put something there.

docker run --rm --volumes-from test-data test sh -c "touch /foo/bar"

Which understandably results in:

touch: /foo/bar: Permission denied

Because the data container has mounted /foo with the permissions root:root

So how do we handle this? With initialization! Remember uncle Ben, with great power comes something something… let’s do it.

docker run --rm --volumes-from test-data test sh -c "su -c 'chown -R test:test /foo' && touch /foo/bar"

Now let’s re-run our previous command:

docker run --rm --volumes-from test-data test

Correctly resulting in:

-rw-r--r--    1 test     test           0 Apr  1 13:05 bar

Security is intact! Let’s double-check that:

docker run --rm --volumes-from test-data test sh -c "touch /foo/baz && ls -lh /foo"

And now we get no errors! Also this:

total 0
-rw-r--r--    1 test     test           0 Apr  1 13:05 bar
-rw-r--r--    1 test     test           0 Apr  1 13:08 baz

Today I learned…

  • Security can be properly handled using a from scratch data container.
  • Backups of a data container can be made easily via docker commands without all the extra distro cruft.
  • If someone does manage to get into your data container there are no commands available and it really can’t be started at all.
  • It can be done!