Docker 数据卷

介绍

镜像本身是只读的,保持不变。从镜像启动一个容器的时候,会在镜像的最上一层创建一个可写层。容器对于文件系统的写操作只会修改可写层,不会修改镜像。

容器运行的过程中产生的数据全都存储到可写层中,当我们删除掉这个容器的时候,同时也会删除掉可写层上的文件。如果有些数据你想一直保存,比如 Web 服务器的日志、数据库管理系统里的数据,怎么办?

我们可以创建一个数据卷,然后将数据卷挂载到容器上指定的目录,这样容器的这个目录便不属于容器的镜像文件系统了,而属于数据卷都对应着的主机上的一个物理目录 /var/lib/docker/volumes/数据卷名/_data。因此将容器的数据保存在数据卷上,就相当于保存到了对应的主机目录上,即便容器被删除了,数据卷中的数据也会一直保存。

命令

docker volume create
docker volume inspect
docker volume ls
docker volume prune
docker volume rm
docker create -v
docker create --volumes-from
docker run -v
docker run --volumes-from

docker volume create

使用 docker volume create 命令创建一个数据卷,该数据卷并没有挂载到任何容器。以下代码创建了一个名称为 foo 的数据卷,该数据卷对应着主机上的 /var/lib/docker/volumes/foo/_data 物理目录。

$ docker volume create foo

docker create -v / docker run -v

使用 docker create -vdocker run -v 命令创建容器时,可以使用 -v 参数将容器的指定目录挂载到指定的数据卷。以下代码创建了一个容器 db1 ,然后将容器的 /data 目录挂载到已经存在的名为 foo 的数据卷。

$ docker create -v foo:/data --name db1 centos

以下代码创建了一个名为 db2 的容器,然后将容器的 /data 目录挂载到名为 bar 的数据卷,由于 bar 数据卷不存在,所以在创建容器的时候会先创建一个名为 bar 的数据卷,然后将 /data 目录挂载到 bar 数据卷,该数据卷对应着主机上的 /var/lib/docker/volumes/bar/_data 物理目录。

$ docker create -v bar:/data --name db2 centos

以下代码创建了一个名为 db3 的容器,然后将容器的 /data 目录挂载到匿名的数据卷。创建容器的时候会先创建一个名为随机字符串的数据卷,然后将 /data 目录挂载到该数据卷,该数据卷对应着主机上的 /var/lib/docker/volumes/随机字符串/_data 物理目录。

$ docker create -v /data --name db3 centos

以下代码创建了一个名为 db4 的容器,然后将容器的 /data 目录挂载到指定的主机目录的绝对路径,这个主机目录并不是数据卷,因此通过数据卷命令 docker volume 无法管理该主机目录。

$ docker create -v /Users/yumanli/Desktop/data:/data --name db4 centos

可以使用 :ro 来绑定只读的数据卷,只能绑定具名数据卷或者主机目录。

$ docker create -v foo:/data:ro --name db1 centos
$ docker create -v /Users/yumanli/Desktop/data:/data:ro --name db4 centos

不能使用 :ro 来绑定匿名数据卷,以下代码会报错。

$ docker create -v /data:ro --name db3 centos

docker volume ls

使用 docker volume ls 命令查看所有的数据卷。

$ docker volume ls
DRIVER              VOLUME NAME
local               6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09
local               bar
local               foo

使用 docker volume ls -f dangling=true 命令查看没有被挂载到容器的数据卷。

$ docker volume create baz
$ docker volume ls -f dangling=true
DRIVER              VOLUME NAME
local               baz

docker volume inspect

使用 docker volume inspect 命令查看数据卷的信息,Name 字段为数据卷的名字,Mountpoint 字段为数据卷挂载的主机目录。

$ docker volume inspect foo bar baz 6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09
[
    {
        "CreatedAt": "2020-01-28T02:29:32Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/foo/_data",
        "Name": "foo",
        "Options": {},
        "Scope": "local"
    },
    {
        "CreatedAt": "2020-01-28T02:29:46Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/bar/_data",
        "Name": "bar",
        "Options": null,
        "Scope": "local"
    },
{
        "CreatedAt": "2020-01-28T03:02:30Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/baz/_data",
        "Name": "baz",
        "Options": {},
        "Scope": "local"
    },
    {
        "CreatedAt": "2020-01-28T02:29:53Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09/_data",
        "Name": "6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09",
        "Options": null,
        "Scope": "local"
    }
]

docker volume rm

使用 docker volume rm 命令删除数据卷,该命令只能删除没有被挂载到容器的数据卷。

$ docker volume rm baz

对于已经被挂载到容器的数据卷,必须先删除相关容器,再删除数据卷。db1 容器挂载了 foo 数据卷,要想删除 foo 数据卷,必须先删除 db1 容器。

$ docker rm db1
$ docker volume rm foo

可以使用 docker rm -v 命令,在删除容器的同时删除该容器挂载的数据卷。该命令只能删除匿名数据卷(名字为一串随机字符串的数据卷),不会删除具名数据卷。db2 容器挂载了 bar 数据卷,db3 容器挂载了匿名数据卷 6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09,使用以下命令不会删除 bar 数据卷。

$ docker rm -v db2 db3
$ docker volume ls
local               bar

docker volume prune

使用 docker volume prune 命令删除所有没有被挂载到容器的数据卷,不管该数据卷是具名的还是匿名的。

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
bar

docker create --volumes-from / docker run --volumes-from

使用 docker create --volumes-fromdocker run --volumes-from 命令创建容器时,可以使用 --volumes-from 参数使得新创建的容器与已有的容器共享数据卷。

以下代码将 db2 容器的 /data 目录与 db1 容器的 /data 目录绑定到同一个具名数据卷 foo (对应着主机上的同一个物理目录 /var/lib/docker/volumes/foo/_data),因此 db1 和 db2 容器可以共享数据。

$ docker create -v foo:/data --name db1 centos
$ docker create --volumes-from db1 --name db2 centos

以下代码可以通过另一种方式实现同样的功能。首先创建一个具名数据卷 foo,然后分别创建两个容器 db1 和 db2,并绑定到这个数据卷 foo,这样也可以实现多个容器共享数据卷。

$ docker volume create foo
$ docker create -v foo:/data --name db1 centos
$ docker create -v foo:/data --name db2 centos

如果一些数据,比如配置文件、数据文件等,要在多个容器之间共享,一种常见的做法是创建一个数据容器,其他容器与之共享 volume。

以下代码先创建了一个名为 db 的容器作为数据容器,将该容器 /data 目录挂载到一个匿名数据卷(也可以挂载到具名数据卷或主机目录)。然后又创建了 db1 和 db2 两个容器,并通过 --volumes-from 参数指定 db1 和 db2 容器与 db 容器共享数据卷,这样 db 容器的 /data 目录、db1 容器的 /data 目录和 db2 容器的 /data 目录都挂载到一个相同的数据卷(对应着主机上的同一个物理目录),因此他们可以共享数据。

$ docker create -v /data --name db centos
$ docker create --volumes-from db --name db1 centos
$ docker create --volumes-from db --name db2 centos

Dockerfile VOLUME

使用 Dockerfile 文件的 VOLUME 参数可以事先指定某个镜像挂载的数据卷。

FROM centos
VOLUME ["/data"]

使用 docker build 命令基于该 Dockerfile 创建一个镜像。

$ docker build -t yumanli/centos .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 470671670cac
Step 2/2 : VOLUME ["/data"]
 ---> Running in 89f3f2cf040f
Removing intermediate container 89f3f2cf040f
 ---> d2cf56c8d1bd
Successfully built d2cf56c8d1bd
Successfully tagged yumanli/centos:latest

通过该镜像创建容器的时候,就不需要通过 -v 参数挂载数据卷了,该容器会使用 Dockerfile 文件的 VOLUME 参数挂载数据卷。

$ docker run --name db yumanli/centos
$ docker inspect db
"Mounts": [
    {
        "Type": "volume",
        "Name": "740bba034eb3e28d0f7fd4227651c0364ec15011db73abdfcd299fce51aa2cbd",
        "Source": "/var/lib/docker/volumes/740bba034eb3e28d0f7fd4227651c0364ec15011db73abdfcd299fce51aa2cbd/_data",
        "Destination": "/data",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

使用 docker run -v 命令创建容器可以在 Dockerfile 文件的 VOLUME 参数基础上挂载新的数据卷。

$ docker run -v /foo --name db2 yumanli/centos
$ docker inspect db2
"Mounts": [
    {
        "Type": "volume",
        "Name": "9b159b8b28e99424937b54b205daa7708db3839e5baa23557cc03bcdc72e60ac",
        "Source": "/var/lib/docker/volumes/9b159b8b28e99424937b54b205daa7708db3839e5baa23557cc03bcdc72e60ac/_data",
        "Destination": "/foo",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    },
    {
        "Type": "volume",
        "Name": "b5cd187a31c03f175f4d576f45b74f8d04f552a5d00d85efe149f0cfa720a9c0",
        "Source": "/var/lib/docker/volumes/b5cd187a31c03f175f4d576f45b74f8d04f552a5d00d85efe149f0cfa720a9c0/_data",
        "Destination": "/data",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342