Development

Docker Bootcamp – Persistent Storage

Storage

Welcome back to my Docker Bootcamp Series. In the first post, I covered the background and installation of Docker, and in the next, I reviewed Docker terminology and gave examples to test out. In this post, I’ll show you how to store persistent data outside your containers and inject data into a container.

Terminology

  • Bind Volume – Connected to a user-specified file or directory on the host system. Useful to share data between the host system and the container and vice versa. Ties a portable container to a known path on the host system. Can cause conflict if multiple containers attempt to write to the same bind volume.
  • Managed Volume – Connected to a location managed by Docker. Keeps a container portable since it does not require any knowledge of the host system. Requires extra diligence when removing containers to ensure volume is removed.
  • Mount – An operating system process that makes a data storage device (flash drive, network storage, optical drive) available to the system.
  • Mount point – A directory where the contents of a mounted device will be displayed.
  • Union File System – All of the layers of an image stacked on top of each other. The container sees the combination of all the layers.  Makes it easy to add changes on top of a base image.  Only the top layer is writable by the container.
  • Volume – A connection between a container and the host file system where persistent data can be stored on the host and shared across containers.
  • Volume Container – A usage pattern where a container simply provides a handle to a volume.

Commands

  • create – Create a new container in a stopped state
  • rm – Remove a container
  • volume – Manage volumes
  • volume inspect – Display details of a volume
  • volume ls – List volumes
  • volume rm – Remove a volume

Command Details

You can find a full list of commands and all available flags at https://docs.docker.com/engine/reference/commandline/docker/.

create

docker create [options] image [command] [args…]
Outputs: ContainerID

–volume <list> -v O Mount a volume
–volumes-from <container> O Mount the volumes defined on the listed container

 

  • Create a bind mount volume
    • -v <host_path>:<path_inside_container>
    • Your host path must be an absolute path
      • You can use $PWD and $PWD/path if you are executing the docker command from within the desired path on the host
  • Create a docker managed volume
    • -v <path_inside_container>
  • Make a read-only volume
    • -v <volume_definition>:ro
  • When using the volumes-from flag
    • You cannot change the volume mount points from the source container
    • You cannot change the volume write permissions from the source container
    • All volumes defined on the container will be included
    • You can create a container using the volumes-from flag multiple times
      • Watch out for volume conflicts

rm

docker rm [options] container [container…]

–volumes -v O Remove any volumes associated with the container

 

volume inspect

docker volume inspect volume_name

volume ls

docker volume ls

 

Examples

 

Container Storage

  • Create an interactive container
    • docker create -it –name bbtest busybox /bin/sh
      • Note the id of the container
  • Start the container
    • docker start -ia bbtest
  • Create a file
    • cd home
    • touch test.txt
    • ls
      • See that the file exists
    • exit
      • Exit and stop the container
  • Start the container
    • docker start -ia bbtest
  • Verify file exits
    • cd home
    • ls
      • See that the file exists
    • exit
      • Exit and stop the container
  • Remove the container
    • docker rm bbtest
  • Create an interactive container
    • docker -it –name bbtest2 busybox /bin/sh
      • Note the id of the container is different than before
  • Start container
    • docker start -ia bbtest2
  • See if the file exists
    • cd home
    • ls
      • See the file does not exist
    • exit
      • Exit and stop the container
  • Remove the container
    • Docker rm bbtest2

Each time a container is created, the image is installed into the empty container.  Only files that exist as part of the image are included in the newly created container.  You can create files inside the container.  The created files will remain in the container after any number of stops and starts. They will be permanently lost when the container is removed.

 

Bind Mount

  • Create a folder on the host to serve as the data volume
    • <path_to_folder>\data
  • Create a text file inside the host data folder and enter some content in the file
    • hostfile.txt
  • Create, start and run an interactive container with a volume
    • docker run -it –name bindmount -v <path_to_folder>\data:/home busybox /bin/sh
  • Validate the file exists inside the container
    • cd home
    • ls
      • See that the file exists
    • cat hostfile.txt
      • View the contents of the file
  • Create a new file
    • touch containerfile.txt
  • View the data folder on the host
    • See that containerfile.txt is created on the host
  • Stop the container
    • exit
  • Remove the container
    • docker rm bindmount
  • View the host data folder
    • Validate the files were not removed
  • Create, start and run a new container with the same volume as before
    • Docker run -it –name bindmount -v <path_to_folder>\data:/home busybox /bin/sh
  • Validate the files exist inside the container
    • cd home
    • ls
      • See that both files exist
  • Update the containerfile.txt from the host
    • Modify <path_to_folder>\data\containerfile.txt
  • View the changed file in the container
    • cat containerfile.txt
  • Create a file on the host
    • <path_to_folder>\data\hostfile2.txt
  • Validate the file exists inside the container
    • ls
      • See that the file exists
  • Stop the container
    • exit
  • Remove the container
    • docker rm bindmount

Using a bind mount, you can inject folders and files into your container at startup as well as have files persist after a container is removed.  The container and the host are both aware of changes made to the volume in real-time.  It is not necessary to restart the container to refresh the content in the volume.  There are several things to remember when using bind mounts:

  • The host path must be an absolute path
  • If the path does not exist on the host, docker will assume it is a folder and create it for you
    • It is not recommended to rely on this functionality
  • You can bind mount a folder
    • If the folder does not exist in the container, it will be available at the defined mount point
    • If the folder already exists in the container, it will be replaced with the contents of the volume
  • You can bind mount an individual file
    • If the file does not exist in the container, It will be available at the defined mount point
      • If the mount point is a directory, the file will be added to the other files in the directory
    • If the file already exists in the container, it will be replaced with the contents of the volume
  • Reusing the same bind mount volume in multiple containers at the same time can cause conflicts

 

Managed Volume

  • Create, start and run an interactive container with a managed volume
    • docker run -it –name managed -v /data busybox /bin/sh
  • Create a new file
    • cd data
    • touch managedfile.txt
    • ls
      • See that the file exists
  • Stop the container
    • exit
  • View the details of the container
    • docker inspect managed
      • Note the name and source properties of the Mounts JSON key
  • Create, start and run an interactive container using volumes from another container
    • docker run -it –name managed2 –volumes-from managed busybox /bin/sh
  • Validate the files exist in the container
    • cd data
    • ls
      • See the managedfile.txt exists
  • Create a new file
    • touch managed2file.txt
    • ls
      • See that the file exists
  • Stop the container
    • Exit
  • View the details of the container
    • docker inspect managed2
      • Note the name and the source properties of the Mounts JSON key
          • They match those of the managed container
  • Remove the managed2 container
    • docker rm -v managed2
        • Be sure to use the -v flag to remove the reference to the volume
  • Validate the volume still exists
    • docker start -ia managed
    • cd data
    • ls
      • See that both files exist
  • Stop the container
    • exit
  • List all docker volumes
    • docker volume ls
      • The volume name from the Mounts JSON of the containers is listed
  • View volume details
    • docker volume inspect <id>
      • The volume mountpoint matches the source of the Mounts JSON of the containers
  • Remove the managed container
    • Docker rm -v managed
      • Be sure to use the -v flag to remove the reference to the volume
  • List all docker volumes
    • Docker volume ls
      • The volume name from the Mounts JSON of the containers is no longer listed

Managed volumes are independent of any container but can only be referenced by the containers that use them.  Managed volumes decouple containers and volumes from the file system of the host.  Docker can delete a managed volume when the last container referencing the volume is removed (docker rm -v).  If you use the volume container pattern, it could be helpful to prefix the name of your containers with “vc_” to make them easily identifiable.

I hope you found this helpful. Keep an eye out for the next post in the series.

About the Author

More from this Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up
Categories