如何处理Docker中的持久存储(例如数据库)

juw*_*ter 969 docker docker-container

人们如何处理Docker容器的持久存储?

我目前正在使用这种方法:构建映像,例如PostgreSQL,然后启动容器

docker run --volumes-from c0dbc34fd631 -d app_name/postgres
Run Code Online (Sandbox Code Playgroud)

恕我直言,有缺点,我不能(偶然)删除容器"c0dbc34fd631".

另一个想法是将主机卷"-v"安装到容器中,但是,用户ID的容器内不一定匹配用户ID从主机,然后权限可能会混乱.

注:与其--volumes-from 'cryptic_id'你也可以使用--volumes-from my-data-container这里my-data-container是你分配到纯数据容器,如姓名docker run --name my-data-container ...(见接受的答案)

tom*_*sop 969

Docker 1.9.0及更高版本

使用volume API

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command
Run Code Online (Sandbox Code Playgroud)

这意味着必须放弃仅数据容器模式以支持新卷.

实际上,卷API只是实现数据容器模式的更好方法.

如果您使用-v volume_name:/container/fs/pathDocker 创建容器,则会自动为您创建一个命名卷,该卷可以:

  1. 通过列出 docker volume ls
  2. 通过.识别 docker volume inspect volume_name
  3. 备份为普通目录
  4. 像以前一样通过--volumes-from连接备份

新的卷API添加了一个有用的命令,可以识别悬空卷:

docker volume ls -f dangling=true
Run Code Online (Sandbox Code Playgroud)

然后通过其名称删除它:

docker volume rm <volume name>
Run Code Online (Sandbox Code Playgroud)

正如@mpugach在评论中强调的那样,你可以用一个漂亮的单行代码摆脱所有悬空音量:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune
Run Code Online (Sandbox Code Playgroud)

Docker 1.8.x及以下版本

似乎最适合生产的方法是使用仅数据容器.

仅数据容器在准系统映像上运行,除了暴露数据卷之外实际上什么都不做.

然后,您可以运行任何其他容器来访问数据容器卷:

docker run --volumes-from data-container some-other-container command-to-execute
Run Code Online (Sandbox Code Playgroud)
  • 在这里,您可以很好地了解如何安排不同的容器.
  • 在这里,您可以很好地了解卷的工作原理.

这篇博文中,有一个很好的描述所谓的容量作为卷模式,它阐明了拥有数据容器的要点.

Docker文档现在将容器的DEFINITIVE描述为volume/s模式.

以下是Docker 1.8.x及更低版本的备份/恢复过程.

备份:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
Run Code Online (Sandbox Code Playgroud)
  • --rm:退出时移除容器
  • --volumes-from DATA:附加到DATA容器共享的卷
  • -v $(pwd):/ backup:bind将当前目录挂载到容器中; 写tar文件到
  • busybox:更简单的图像 - 有助于快速维护
  • tar cvf /backup/backup.tar/data:创建/ data目录中所有文件的未压缩tar文件

恢复:

# 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
Run Code Online (Sandbox Code Playgroud)

这是来自优秀的Brian Goff的一篇很好的文章,解释了为什么对容器和数据容器使用相同的图像是好的.

  • 是的,从Docker 1.9开始,使用Volumes API创建命名卷(`docker volume create --name mydata`)比数据卷容器更受欢迎.Docker的人们自己建议数据量容器"[不再被认为是推荐模式](https://github.com/docker/docker/issues/20465),""[命名卷应该能够替换仅数据大多数(如果不是全部)情况下的卷(https://github.com/docker/docker/issues/17798),"和"[我没理由看到只使用数据容器](https:// github .COM /泊坞窗/泊坞窗/问题/ 17798)". (10认同)
  • 数据容器没有任何意义,真是个坏主意!容器仅在进程运行时表示某些内容,否则它只是一个主机文件系统.您可以使用-v安装卷,这是唯一且最佳选择.您可以控制您使用的文件系统和物理磁盘. (9认同)
  • 它是满足不同需求的不同工具.`--volumes-from`让你共享磁盘空间`--link`让你共享服务. (8认同)
  • @coding,我很伤心你很伤心,部分是因为你在3年的延迟判断答案,部分是因为答案基本上是正确的.如果您有任何建议,请随时发表评论,以便我可以整合答案,帮助人们不要悲伤 (7认同)
  • 还有另一个项目专门针对这类事情,可能会将其添加到这个答案作为参考观看?https://github.com/ClusterHQ/flocker (3认同)
  • @Spock这将是一个长时间的讨论,也许这里不是一个正确的地方.但是,除了容器只是一个进程周围的内核命名空间这一事实外,容器有什么问题要解决?我告诉你,可变的基础设施以及他们是如何做到的?使用不可变容器以及我们使用所谓的"数据容器"做什么?创建可变容器!这是纯粹的矛盾.上述问题可以通过即将推出的Docker存储驱动程序解决.同时,对数据容器说不 - 不! (2认同)

ami*_*ula 71

Docker发行版v1.0中,可以通过给定的命令在主机上绑定文件或目录的安装:

$ docker run -v /host:/container ...
Run Code Online (Sandbox Code Playgroud)

上述卷可以用作运行Docker的主机上的持久存储.

  • 这应该是推荐的答案,因为它远不如目前有更多选票的量容器方法复杂 (3认同)
  • 我希望在使用此卷安装命令时,有一个标志来指定host-uid:container-uid和host-gid:container-gid映射。 (2认同)

toa*_*oza 31

从Docker Compose 1.6开始,Docker Compose现在改进了对数据量的支持.以下撰写文件将创建一个数据映像,该映像将在父容器的重新启动(甚至删除)之间保持不变:

以下是博客公告:Compose 1.6:New Compose文件,用于定义网络和卷

这是一个组合文件的示例:

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:
Run Code Online (Sandbox Code Playgroud)

据我所知:这将创建一个数据卷容器(db_data),它将在重新启动之间保持不变.

如果您运行:docker volume ls您应该看到您的卷列出:

local               mypthonapp_db-data
...
Run Code Online (Sandbox Code Playgroud)

您可以获得有关数据量的更多详细信息:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]
Run Code Online (Sandbox Code Playgroud)

一些测试:

# 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).
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 您还可以在volumes块中指定各种驱动程序.例如,您可以为db_data指定Flocker驱动程序:

    volumes:
      db-data:
        driver: flocker
    
    Run Code Online (Sandbox Code Playgroud)
  • 随着他们改进Docker Swarm和Docker Compose之间的集成(并且可能开始将Flocker集成到Docker生态系统中(我听说Docker已经购买了Flocker的传闻),我认为这种方法应该变得越来越强大.

免责声明:这种方法很有前景,我在开发环境中成功使用它.我还是很担心在生产中使用它!


ben*_*kly 17

如果从所选答案的更新5中不清楚,从Docker 1.9开始,您可以创建可以存在但不与特定容器关联的卷,从而使"仅数据容器"模式过时.

请参阅使用docker 1.9.0过时的仅限数据的容器?#17798.

我认为Docker维护者意识到仅数据容器模式有点像设计气味,并决定使卷成为一个独立的实体,可以在没有相关容器的情况下存在.


Tim*_*orr 13

虽然这仍然是Docker的一部分需要一些工作,但您应该使用VOLUME指令将卷放在Dockerfile中,这样您就不需要从另一个容器中复制卷.

这将使您的容器减少相互依赖,并且您不必担心删除一个影响另一个容器的容器.

  • Docker的这份官方指南另有说明:http://docs.docker.com/userguide/dockervolumes/#backup-restore-or-migrate-data-volumes"数据卷旨在保存数据,与容器的生命周期无关.因此,当您删除容器时,Docker永远不会自动删除卷,也不会"垃圾收集"容器不再引用的卷." (2认同)

Cza*_*ino 12

使用Docker Compose时,只需附加一个命名卷,例如,

version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - db_data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: root
volumes:
  db_data:
Run Code Online (Sandbox Code Playgroud)


Ram*_*man 9

@ tommasop的答案很好,并解释了使用仅数据容器的一些机制.但是,有人最初认为数据容器是愚蠢的,当一个人可以将卷装入主机(如其他几个答案所示),但现在意识到实际上只有数据的容器非常整洁,我可以建议我自己关于此主题的博客文章:为什么Docker数据容器(卷!)是好的

另请参阅:对" 管理Docker共享卷权限的最佳方法是什么? " 这一问题的回答,以获取如何使用数据容器来避免诸如权限和与主机的uid/gid映射之类的问题的示例.

解决OP的一个原始问题:不得删除数据容器.即使删除了数据容器,只要任何容器具有对该卷的引用,即任何通过该卷安装卷的容器,数据本身都不会丢失--volumes-from.因此,除非停止并删除所有相关容器(可以认为这相当于意外rm -fr /),否则数据是安全的.您始终可以通过执行--volumes-from任何具有该卷引用的容器来重新创建数据容器.

一如既往,尽管做备份!

更新:Docker现在拥有可以独立于容器进行管理的卷,这使得这更容易管理.


Wil*_*ern 9

管理持久性数据有多个级别,具体取决于您的需求:

  • 将其存储在您的主机上
    • 使用该标志-v host-path:container-path将容器目录数据持久保存到主机目录.
    • 通过运行安装到同一目录的备份/恢复容器(例如tutumcloud/dockup)来进行备份/恢复.
  • 创建数据容器并将其卷装入应用程序容器
    • 创建导出数据卷的容器,用于--volumes-from将该数据装入应用程序容器.
    • 备份/恢复与上述解决方案相同.
  • 使用支持外部/第三方服务的Docker卷插件
    • Docker卷插件允许您的数据源来自任何地方 - NFS,AWS(S3,EFS和EBS)
    • 根据插件/服务,您可以将单个或多个容器附加到单个卷.
    • 根据服务的不同,备份/恢复可能会自动为您服务.
    • 虽然手动操作很麻烦,但是一些编排解决方案 - 例如Rancher - 已经融入其中并且易于使用.
    • Convoy是手动执行此操作的最简单方法.


小智 8

如果你想移动你的音量,你也应该看看Flocker.

来自README:

Flocker是一个数据卷管理器和多主机Docker集群管理工具.有了它,您可以使用与无状态应用程序相同的工具来控制数据,方法是利用Linux上ZFS的强大功能.

这意味着您可以在Docker中运行数据库,队列和键值存储,并像应用程序的其余部分一样轻松移动它们.


ben*_*rtz 5

这取决于您的场景(这不适合生产环境),但这是一种方式:

创建MySQL Docker容器

它的要点是使用主机上的目录来实现数据持久性.

  • 但是感谢Ben - 我可以通过这种方法看到的一个问题:文件系统资源(目录,文件)将由docker/lxc容器(guest)中的uid拥有 - 一个可能与uid发生冲突的容器在主持人...... (6认同)