3.8 KiB
Lesson 4: Persisting data
-
Change directory into
lesson04
. -
We saw in Lesson 3 that data written to the final container layer does not persist. How do we deal with this? One option is to have the container write to an external system like a database system or cloud storage. There is, however, another method: mounting a local file system or directory.
-
Let's create a Docker container that saves the current date to a file. Here is our first attempt:
# Dockerfile FROM debian:buster-slim LABEL maintainer="adamhl@stanford.edu" ADD date.sh /root/date.sh RUN chmod a+x /root/date.sh CMD /root/date.sh # date.sh #!/bin/sh echo "echoing date to /tmp/date.output" date > /tmp/date.output $ docker build . -t date $ docker run --rm --name=fuzzle date echoing date to /tmp/date.output
-
The above will create the file
/tmp/date.output
containing the date but we know that the file will not persist after the container stops running. To get around this we "mount" a local directory into the container's/tmp
directory. By "local directory" we mean a directory on the computer where we run the ourdocker
commands. We mount the colume when we run the container.$ mkdir -p /tmp/docker $ docker run --rm --name=fuzzle --volume=/tmp/docker:/tmp date echoing date to /tmp/date.output $ cat /tmp/docker/date.output
-
You can run a container and override the
CMD
command.$ docker run --rm --name=fuzzle date ls -ld /etc drwxr-xr-x 1 root root 4096 Jan 17 17:23 /etc/ (The date.sh script did NOT run)
-
This is especially useful when you want to login to the container and debug the filesystem or CMD command.
-
You can overwrite a file in the image using the same
--volume
option. For example, let's overwrite/etc/debian_version
with a different file.$ docker run --rm --name=fuzzle date cat /etc/debian_version 10.7 $ echo "fake-version" > /tmp/deb_ver $ docker run --rm --name=fuzzle --volume=/tmp/deb_ver:/etc/debian_version date cat /etc/debian_version fake-version
-
If you mount an external directory onto a container directory everything in the directory in the container is replaced with the external directory.
$ docker run --rm --name=fuzzle date ls -l /usr total 32 drwxr-xr-x 2 root root 4096 Jan 11 00:00 bin drwxr-xr-x 2 root root 4096 Nov 22 12:37 games ... more ... # Create a directory in /tmp with a single file. $ mkdir -p /tmp/usr; cp test.txt /tmp/usr # Mount /tmp/usr over /usr in the container $ docker run --rm --name=fuzzle --volume=/tmp/usr:/usr date ls -l /usr total 4 -rw-r--r-- 1 52777 root 7 Jan 17 18:04 test.txt
-
You can mount an external directory in read-only mode. This is particularly useful when injecting secrets or configuration information into a container. Look for the
ro
in the--volume
option below.$ mkdir -p /tmp/secrets $ echo "my-password" > /tmp/secrets/password $ docker run --rm --name=fuzzle --volume=/tmp/secrets:/secrets:ro date sleep 100000 & $ docker exec -ti fuzzle /bin/sh # cat /secrets/password my-password # echo "another secret" >> /secrets/password /bin/sh: 5: cannot create /secrets/password: Read-only file system $ docker kill fuzzle
-
You can run the entire container in read-only mode. The
docker run
option--read-only
mounts the root filesystem (i.e., everything) in read-only excepting any externally mounted volumes. This lets you lock-down the filesystem except for those parts of the filesystem you know need to be written to (e.g.,/tmp
,/var/log
, etc.).