This post is part of the series Dev with Docker
Other posts in this series:
- Dev with Docker
- Data Persistence with Docker Volumes (Current)
- Reaching localhost from a Docker container
Docker containers are designed to be ephemeral. You can destroy one and spin up an exact replica in seconds. Everything that defines the container can be found in the Dockerfile
that declares how to build it.
This model does not, however, explain what to do with persistent data. Things like databases or uploaded media. In a production environment, I would recommend delegating these tasks to an external service, like Amazon’s RDS or S3.
For local development, though, you can use volumes for storing persistent data. Volumes come in two main flavors: data volumes and host directory mounts.
The latter is perhaps the most straightforward. You connect a directory in your container to a directory on your host machine, so they are essentially sharing the file system. Indeed, when you’re actively working on code, this is the simplest way to share your local code with your running containers. Mount the root directory of your project as a volume in your container, and anytime you update code, your container will also have the updates.
# docker run --rm -it -v="/your/local/dir:/srv/www/public" nginx:stable-alpine /bin/sh
This runs a container that has its /srv/www/public
directory shared with your host system’s /your/local/dir
directory. Updates you make to files either on your local system or in the container are automatically shared with the other.
Data volumes do not map directly to your host filesystem. Docker stores the data somewhere, and you generally don’t need to know where that is. When using Docker for Mac, one of the key differences is that a host mount shares files using osxfs (which currently has some performance issues) while a data volume stores its data inside the Docker virtual machine (which is subsequently much more performant for I/O). While I use host mounts for things like uploaded media, I prefer to use a data volume for storing databases.
# docker volume create --name=mysqldata
Once the volume is created, you can mount it into one or more containers.
# docker run --rm -v="mysqldata:/var/lib/mysql" mysql:5.5
The contents of our volume “mysqldata” will be available to MySQL in the /var/lib/mysql
directory. The data volume itself doesn’t have a directory name (in contrast to the prior best practice of using a directory within a data-only containers). I think of a volume as a single directory that can be mounted wherever I want in a container.
Continue reading this series:
Reaching localhost from a Docker container