How to deal with persistent storage (e.g. databases) in Docker
人们如何处理码头集装箱的持久存储?
我目前使用的方法是:构建图像,例如PostgreSQL,然后用
1 | docker run --volumes-from c0dbc34fd631 -d app_name/postgres |
imho,这有一个缺点,那就是我决不能(偶然)删除容器"c0dbc34fd631"。
另一个想法是将主机卷"-v"装载到容器中,但是容器中的用户ID不一定与主机中的用户ID匹配,然后权限可能会混乱。
注:除
docker 1.9.0和以上
使用API卷
1 2 | docker volume create --name hello docker run -d -v hello:/container/path/for/volume container_image my_command |
这意味着你只集装箱的数据模式发现的研究在一定favour新卷。
实际上,API是唯一一个更好的卷方式以实现集装箱-什么是数据的模式。
如果你创建一个容器与一个
增加了新的卷的一个有用的API命令,让你识别dangling卷:
1 | docker volume ls -f dangling=true |
然后消除它通过它的名字:
1 | docker volume rm <volume name> |
作为mpugach underlines @在评论,你可以摆脱所有的dangling卷与尼斯一liner:
1 2 3 | docker volume rm $(docker volume ls -f dangling=true -q) # Or using 1.13.x docker volume prune |
docker 1.8.x和下面
工作的方法,似乎是一个最佳的生产使用的数据只集装箱。
唯一的数据是在一个集装箱barebones颤抖的图像和数据exposing实际上并不没有什么除了一卷。
然后你可以运行其他任何集装箱货柜有Access的数据卷:
1 | docker run --volumes-from data-container some-other-container command-to-execute |
- 在这里你可以得到一个很好的图片的arrange如何不同的容器。
- 在这里有一个很好的洞察力如何卷工作。
在这个博客后,有一个很好的描述,所以称为集装箱作为研究的主要clarifies卷模式,只有在数据点的容器。
现在docker文件已明确描述的体积的容器作为/ S模式。
以下是restore backup /过程为docker 1.8.x和下面的。
backup:
1 | sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data |
- ——rm:删除当它exits的集装箱
- ——从数据:attach卷的卷由集装箱数据共享
- - V(pwd美元/ backup):当前目录:bind芒特进入集装箱的焦油写大文件、大
- 一个小的简单的图像busybox:好的,对于快速维护
- cvf backup backup.tar焦油/ / /数据安全:creates uncompressed焦油文件所有文件在/数据目录
restore:
1 2 3 4 5 6 7 8 9 | # Create a new data container $ sudo docker run -v /data -name DATA2 busybox true # untar the backup files into the new container?s data volume $ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar data/ data/sven.txt # Compare to the original container $ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data sven.txt |
这里是一个很好的文章解释为什么它是一个优秀的Brian Goff好大,使用相同的图像数据,对于一个容器和一个集装箱。
在一个v1.0 docker稿,结合机器翻译的文件或目录在宿主机器不能做的由给定的命令:
1 | $ docker run -v /host:/container ... |
以上的卷可以用于作为一个持续的存储在运行docker寄主。
从Docker Compose 1.6开始,现在Docker Compose中对数据量的支持得到了改进。以下撰写文件将创建一个数据映像,该映像将在父容器重新启动(甚至删除)之间保持:
以下是博客公告:撰写1.6:定义网络和卷的新撰写文件
下面是一个编写文件的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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: |
据我所知:这将创建一个数据卷容器(
如果您运行:
1 2 | local mypthonapp_db-data ... |
您可以获得有关数据卷的更多详细信息:
1 2 3 4 5 6 7 8 | docker volume inspect mypthonapp_db-data [ { "Name":"mypthonapp_db-data", "Driver":"local", "Mountpoint":"/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data" } ] |
一些测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # 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). |
笔记:
您还可以在
volumes 块中指定各种驱动程序。例如,可以为db_数据指定Flocker驱动程序:1
2
3volumes:
db-data:
driver: flocker- 随着他们改善了Docker Swarm和Docker Compose之间的集成(并可能开始将Flocker集成到Docker Eco系统中(我听说Docker收购了Flocker),我认为这种方法应该变得越来越强大。
免责声明:这种方法是有前途的,我正在开发环境中成功地使用它。我很担心在制作中使用这个!
如果从所选答案的更新5中不清楚,从Docker 1.9开始,您可以创建不与特定容器关联的卷,从而使"仅数据容器"模式过时。
见数据专用容器与Docker 1.9.0一起废弃?17798。
我认为Docker维护人员意识到只有数据的容器模式有点设计上的味道,并决定让卷成为一个独立的实体,不需要关联的容器就可以存在。
而这是一部分,docker仍然需要一些工作,你应该他妈的在dockerfile卷与卷的指导,所以你不需要复制的卷从另一个集装箱。
这会让你的inter容器不依赖的和你不担心有关于集装箱的deletion affecting的一另一个。
使用Docker Compose时,只需附加一个命名卷,例如,
1 2 3 4 5 6 7 8 9 10 | version: '2' services: db: image: mysql:5.6 volumes: - db_data:/var/lib/mysql:rw environment: MYSQL_ROOT_PASSWORD: root volumes: db_data: |
@Tommasop的答案很好,并解释了使用仅数据容器的一些机制。但是,作为一个最初认为数据容器是愚蠢的人,当一个人可以将挂载卷绑定到主机上时(正如其他几个答案所建议的那样),但现在意识到事实上,只有数据容器是非常整洁的,我可以建议我自己的博客关于这个主题的文章:为什么要使用Docker数据容器(volumes!)是好的
另请参见:我对问题"管理Docker共享卷权限的(最佳)方法是什么?"例如,如何使用数据容器来避免权限和与主机的uid/gid映射等问题。
为了解决OP最初的一个问题:不能删除数据容器。即使删除了数据容器,只要任何容器引用了该卷(即通过
像往常一样,做备份!
更新:Docker现在有了可以独立于容器管理的卷,这使得管理更加容易。
根据您的需要,有几种级别的管理持久性数据:
- 把它存储在你的主机上
- 使用标志
-v host-path:container-path 将容器目录数据保存到主机目录。 - 备份/还原通过运行装载到同一目录的备份/还原容器(如tutumcloud/dockup)来完成。
- 使用标志
- 创建数据容器并将其卷装载到应用程序容器中
- 创建一个导出数据卷的容器,使用
--volumes-from 将数据装载到应用程序容器中。 - 备份/恢复与上述解决方案相同。
- 创建一个导出数据卷的容器,使用
- 使用支持外部/第三方服务的Docker卷插件
- Docker卷插件允许您的数据源来自任何地方-NFS、AWS(S3、EFS和EBS)
- 根据插件/服务的不同,可以将单个或多个容器附加到单个卷。
- 根据服务的不同,备份/恢复可能会为您实现自动化。
- 虽然手工操作很繁琐,但一些编排解决方案(如Rancher)却很容易实现并易于使用。
- 护航是最简单的手动解决方案。
如果你想移动你周围的体积,你也应该看看植绒。
从自述文件:
Flocker is a data volume manager and multi-host Docker cluster management tool. With it you can control your data using the same tools you use for your stateless applications by harnessing the power of ZFS on Linux.
This means that you can run your databases, queues and key-value stores in Docker and move them around as easily as the rest of your application.
这取决于你的scenario(这不是真的,对于一个生产环境suitable),但这里是一个方法:
创造一个mysql docker集装箱
这是一个gist使用它在你的主机persistence目录数据。
我最近写了一个潜在的解决方案和一个演示该技术的应用程序。我发现它在开发和生产过程中非常有效。希望它能帮助或激发一些想法。
报告:https://github.com/levinteractive/docker-nodejs-example文章:http://lev-interactive.com/2015/03/30/docker-load-balanced-mongodb-persistence/
我只是在主机上使用一个预定义的目录来为PostgreSQL保存数据。此外,通过这种方式,可以轻松地将现有的PostgreSQL安装迁移到Docker容器:https://crondev.com/persistent-postgresql-inside-docker/
使用来自kubernetes的持久卷声明(pvc),这是一个Docker容器管理和调度工具:
持久卷
为此目的使用Kubernetes的优势在于:
- 您可以使用任何存储,如NFS或其他存储,即使在节点关闭时,也不必使用存储。
- 此外,这些卷中的数据可以配置为即使在容器本身被销毁后也可以保留,以便在必要时由另一个容器回收。
我的解决方案是使用新的
因此,我的systemd init脚本将数据库备份到主机上的一个归档文件中。我在文件名中放置了一个时间戳,以避免重写文件。
在ExecStartPre上进行:
1 2 | 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' |
它在execstopast上也做了同样的事情:
1 2 | 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' |
另外,我将一个文件夹作为一个卷从主机暴露到与数据库存储位置完全相同的位置:
1 2 3 4 | mariadb: build: ./mariadb volumes: - $HOME/server/mysql/:/var/lib/mysql/:rw |
它在我的虚拟机上工作得很好(我为自己构建了一个LEMP堆栈):https://github.com/dj小提琴/lemp
但我只是不知道当你的生活实际上依赖于它时,它是否是一个"防弹"的解决方案(例如,在任何可能的毫秒内进行交易的Webshop)?
在距官方Docker主题演讲视频20分钟20秒处,演示者对数据库做了同样的事情:
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."