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

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

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

恕我直言,这有缺点,我不能(意外地)删除容器“c0dbc34fd631”。

另一个想法是将主机卷“-v”挂载到容器中,然而,容器中的用户id不一定与来自主机的用户id匹配,然后权限可能会被打乱。

注意:除了——volumes-from 'cryptic_id',你还可以使用——volumes-from my-data-container,其中my-data-container是你分配给仅数据容器的名称,例如docker run——name my-data-container…(见公认答案)


虽然这仍然是Docker需要做一些工作的一部分,但你应该将卷与volume指令放在Dockerfile中,这样你就不需要从另一个容器复制卷了。

这将降低容器的相互依赖性,并且不必担心删除一个容器会影响另一个容器。


这取决于你的场景(这并不适合生产环境),但这里有一种方法:

创建MySQL Docker容器

它的要点是使用主机上的目录进行数据持久性。


Docker 1.9.0及以上版本

使用卷API

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

这意味着必须放弃纯数据容器模式,转而使用新卷。

实际上,卷API只是实现数据容器模式的一种更好的方式。

如果你用-v volume_name:/container/fs/path创建一个容器,Docker会自动为你创建一个命名卷,它可以:

通过docker卷ls列出 通过docker卷inspect volume_name进行识别 备份为普通目录 通过——volumes-from连接像以前一样备份

新的卷API增加了一个有用的命令,可以让你识别悬挂的卷:

docker volume ls -f dangling=true

然后通过它的名字删除它:

docker volume rm <volume name>

正如@mpugach在评论中强调的那样,你可以用一行漂亮的语句摆脱所有悬浮的卷:

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

码头工人1.8。X及以下

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

仅数据容器在一个基本映像上运行,实际上除了公开一个数据卷外什么也不做。

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

docker run --volumes-from data-container some-other-container command-to-execute

在这里,您可以很好地了解如何安排不同的容器。 这里有一个关于容量如何工作的很好的见解。

在这篇博客文章中,对所谓的容器作为体积模式进行了很好的描述,阐明了只有数据容器的主要观点。

Docker文档现在有了容器的volume/s模式的权威描述。

下面是Docker 1.8的备份/恢复过程。X及以下。

备份:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data

——rm:当容器退出时将其移除 ——volumes-from DATA:附加到DATA容器共享的卷上 -v $(pwd):/backup:将当前目录挂载到容器中;将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

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


在Docker v1.0版本中,可以通过以下命令绑定主机上的文件或目录的挂载:

$ docker run -v /host:/container ...

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


@tommasop的回答很好,并解释了使用仅数据容器的一些机制。但是,有些人最初认为数据容器很愚蠢,因为可以将一个卷绑定到主机上(正如其他几个答案所建议的那样),但现在意识到实际上只有数据的容器非常整洁,我可以推荐我自己的博客文章:为什么Docker数据容器(卷!)很好

请参见:我对“管理Docker共享卷权限的(最佳)方法是什么?”的回答,以获得如何使用数据容器来避免权限和与主机的uid/gid映射等问题的示例。

To address one of the OP's original concerns: that the data container must not be deleted. Even if the data container is deleted, the data itself will not be lost as long as any container has a reference to that volume i.e. any container that mounted the volume via --volumes-from. So unless all the related containers are stopped and deleted (one could consider this the equivalent of an accidental rm -fr /) the data is safe. You can always recreate the data container by doing --volumes-from any container that has a reference to that volume.

和往常一样,做备份!

更新:Docker现在有了可以独立于容器管理的卷,这进一步简化了管理。


如果你想移动你的卷,你也应该看看Flocker。

自述:

Flocker是一个数据卷管理器和多主机Docker集群管理工具。有了它,您可以利用Linux上ZFS的强大功能,使用与用于无状态应用程序相同的工具来控制数据。 这意味着你可以在Docker中运行你的数据库、队列和键值存储,并且像移动应用程序的其他部分一样轻松。


我最近写了一篇关于潜在解决方案和演示该技术的应用程序的文章。我发现它在开发和生产过程中非常有效。希望它能帮助或激发一些想法。

回购:https://github.com/LevInteractive/docker-nodejs-example 文章:http://lev-interactive.com/2015/03/30/docker-load-balanced-mongodb-persistence/


我的解决方案是使用新的docker cp,它现在能够从容器中复制数据,无论它是否运行,并将一个主机卷共享到数据库应用程序在容器中创建其数据库文件的同一位置。这种双重解决方案在不使用纯数据容器的情况下工作,直接使用原始数据库容器。

因此,我的systemd init脚本负责将数据库备份到主机上的存档中。我在文件名中放置了时间戳,以便永远不会重写文件。

它在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'

它也在ExecStopPost上做同样的事情:

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'

另外,我将主机上的一个文件夹作为卷暴露到数据库存储的相同位置:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

它在我的VM上工作得很好(我为自己构建了一个LEMP堆栈):https://github.com/DJviolin/LEMP

但我只是不知道当你的生活实际上依赖于它时,它是否是一个“防弹”的解决方案(例如,在任何可能的毫秒内进行交易的网上商店)?

在官方Docker主题演讲视频的20分20秒中,演示者对数据库做了同样的事情:

Docker入门

“对于数据库,我们有一个卷,所以我们可以确保,当数据库容器停止时,随着数据库的上升和下降,我们不会丢失数据。”


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

查看docker 1.9.0中仅数据容器已过时?# 17798。

我认为Docker的维护者意识到只有数据的容器模式有点设计的味道,所以决定让卷成为一个独立的实体,可以在没有关联容器的情况下存在。


我只是在主机上使用一个预定义的目录来持久化PostgreSQL的数据。同样,通过这种方式,可以轻松地将现有的PostgreSQL安装迁移到Docker容器:https://crondev.com/persistent-postgresql-inside-docker/


从Docker Compose 1.6开始,现在在Docker Compose中改进了对数据卷的支持。下面的合成文件将创建一个数据映像,该映像将在父容器重新启动(甚至删除)之间持续存在:

下面是博客公告:Compose 1.6:用于定义网络和卷的新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:

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

如果你运行:docker volume ls,你会看到你的卷被列出:

local               mypthonapp_db-data
...

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

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

一些测试:

# 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).

注:

您还可以在卷块中指定各种驱动程序。例如,你可以为db_data指定Flocker驱动程序: 卷: db-data: 司机:群 随着Docker Swarm和Docker Compose之间的集成越来越完善(并且可能开始将Flocker集成到Docker生态系统中(我听说Docker已经收购了Flocker),我认为这种方法应该会变得越来越强大。

声明:这种方法很有前途,我在开发环境中成功地使用了它。我对在生产中使用它感到不安!


使用Kubernetes的Persistent Volume Claim (PVC),这是一个Docker容器管理和调度工具:

持久的卷

为此目的使用Kubernetes的优点是:

您可以使用任何存储,如NFS或其他存储,即使节点宕机,存储也不需要。 此外,这些卷中的数据可以配置为即使在容器本身被销毁后也可以保留,以便在必要时由另一个容器回收。


使用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:

根据您的需要,管理持久数据有几个级别:

Store it on your host Use the flag -v host-path:container-path to persist container directory data to a host directory. Backups/restores happen by running a backup/restore container (such as tutumcloud/dockup) mounted to the same directory. Create a data container and mount its volumes to your application container Create a container that exports a data volume, use --volumes-from to mount that data into your application container. Backup/restore the same as the above solution. Use a Docker volume plugin that backs an external/third-party service Docker volume plugins allow your datasource to come from anywhere - NFS, AWS (S3, EFS, and EBS) Depending on the plugin/service, you can attach single or multiple containers to a single volume. Depending on the service, backups/restores may be automated for you. While this can be cumbersome to do manually, some orchestration solutions - such as Rancher - have it baked in and simple to use. Convoy is the easiest solution for doing this manually.


要保存或存储数据库数据,请确保docker-compose。Yml看起来就像 如果你想使用Dockerfile

version: '3.1'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html/
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - mysql-data:/var/lib/mysql

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
volumes:
  mysql-data:

你的docker-compose。Yml将看起来像 如果您想使用您的映像而不是Dockerfile

version: '3.1'   

services:
  php:
    image: php:7.4-apache
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html/
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - mysql-data:/var/lib/mysql

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
volumes:

如果你想存储或保存mysql的数据,那么 必须记得在docker-compose.yml中添加两行

volumes:
  - mysql-data:/var/lib/mysql

and

volumes:
  mysql-data:

之后使用此命令

docker-compose up -d

现在您的数据将被持久化,即使在使用此命令后也不会被删除

docker-compose down

额外:-但如果你想删除所有的数据,那么你将使用

docker-compose down -v

此外,您还可以使用此命令检查数据库数据列表

docker volume ls

DRIVER              VOLUME NAME
local               35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local               133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local               483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local               725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local               de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local               phphelloworld_mysql-data