How do people deal with persistent storage for your Docker containers?
I am currently using this approach: build the image, e.g. for PostgreSQL, and then start the c
When using Docker Compose, simply attach a named volume, for example:
version: '2'
services:
db:
image: mysql:5.6
volumes:
- db_data:/var/lib/mysql:rw
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
db_data:
My solution is to get use of the new docker cp
, which is now able to copy data out from containers, not matter if it's running or not and share a host volume to the exact same location where the database application is creating its database files inside the container. This double solution works without a data-only container, straight from the original database container.
So my systemd init script is taking the job of backuping the database into an archive on the host. I placed a timestamp in the filename to never rewrite a file.
It's doing it on the ExecStartPre:
ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'
And it is doing the same thing on ExecStopPost too:
ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'
Plus I exposed a folder from the host as a volume to the exact same location where the database is stored:
mariadb:
build: ./mariadb
volumes:
- $HOME/server/mysql/:/var/lib/mysql/:rw
It works great on my VM (I building a LEMP stack for myself): https://github.com/DJviolin/LEMP
But I just don't know if is it a "bulletproof" solution when your life depends on it actually (for example, webshop with transactions in any possible miliseconds)?
At 20 min 20 secs from this official Docker keynote video, the presenter does the same thing with the database:
Getting Started with Docker
"For the database we have a volume, so we can make sure that, as the database goes up and down, we don't loose data, when the database container stopped."
In Docker release v1.0, binding a mount of a file or directory on the host machine can be done by the given command:
$ docker run -v /host:/container ...
The above volume could be used as a persistent storage on the host running Docker.
In case it is not clear from update 5 of the selected answer, as of Docker 1.9, you can create volumes that can exist without being associated with a specific container, thus making the "data-only container" pattern obsolete.
See Data-only containers obsolete with docker 1.9.0? #17798.
I think the Docker maintainers realized the data-only container pattern was a bit of a design smell and decided to make volumes a separate entity that can exist without an associated container.
While this is still a part of Docker that needs some work, you should put the volume in the Dockerfile with the VOLUME instruction so you don't need to copy the volumes from another container.
That will make your containers less inter-dependent and you don't have to worry about the deletion of one container affecting another.
As of Docker Compose 1.6, there is now improved support for data volumes in Docker Compose. The following compose file will create a data image which will persist between restarts (or even removal) of parent containers:
Here is the blog announcement: Compose 1.6: New Compose file for defining networks and volumes
Here's an example compose file:
version: "2"
services:
db:
restart: on-failure:10
image: postgres:9.4
volumes:
- "db-data:/var/lib/postgresql/data"
web:
restart: on-failure:10
build: .
command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
volumes:
db-data:
As far as I can understand: This will create a data volume container (db_data
) which will persist between restarts.
If you run: docker volume ls
you should see your volume listed:
local mypthonapp_db-data
...
You can get some more details about the data volume:
docker volume inspect mypthonapp_db-data
[
{
"Name": "mypthonapp_db-data",
"Driver": "local",
"Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
}
]
Some testing:
# Start the containers
docker-compose up -d
# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...
# Stop and remove the containers:
docker-compose stop
docker-compose rm -f
# Start it back up again
docker-compose up -d
# Verify the data is still there
...
(it is)
# Stop and remove with the -v (volumes) tag:
docker-compose stop
docker=compose rm -f -v
# Up again ..
docker-compose up -d
# Check the data is still there:
...
(it is).
Notes:
You can also specify various drivers in the volumes
block. For example, You could specify the Flocker driver for db_data:
volumes:
db-data:
driver: flocker
Disclaimer: This approach is promising, and I'm using it successfully in a development environment. I would be apprehensive to use this in production just yet!