介紹
鏡像本身是只讀的,保持不變荠察。從鏡像啟動(dòng)一個(gè)容器的時(shí)候译柏,會(huì)在鏡像的最上一層創(chuàng)建一個(gè)可寫層镣煮。容器對(duì)于文件系統(tǒng)的寫操作只會(huì)修改可寫層,不會(huì)修改鏡像鄙麦。
容器運(yùn)行的過(guò)程中產(chǎn)生的數(shù)據(jù)全都存儲(chǔ)到可寫層中典唇,當(dāng)我們刪除掉這個(gè)容器的時(shí)候,同時(shí)也會(huì)刪除掉可寫層上的文件胯府。如果有些數(shù)據(jù)你想一直保存介衔,比如 Web 服務(wù)器的日志、數(shù)據(jù)庫(kù)管理系統(tǒng)里的數(shù)據(jù)骂因,怎么辦炎咖?
我們可以創(chuàng)建一個(gè)數(shù)據(jù)卷,然后將數(shù)據(jù)卷掛載到容器上指定的目錄,這樣容器的這個(gè)目錄便不屬于容器的鏡像文件系統(tǒng)了乘盼,而屬于數(shù)據(jù)卷都對(duì)應(yīng)著的主機(jī)上的一個(gè)物理目錄 /var/lib/docker/volumes/數(shù)據(jù)卷名/_data升熊。因此將容器的數(shù)據(jù)保存在數(shù)據(jù)卷上,就相當(dāng)于保存到了對(duì)應(yīng)的主機(jī)目錄上绸栅,即便容器被刪除了级野,數(shù)據(jù)卷中的數(shù)據(jù)也會(huì)一直保存。
命令
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
命令創(chuàng)建一個(gè)數(shù)據(jù)卷粹胯,該數(shù)據(jù)卷并沒(méi)有掛載到任何容器蓖柔。以下代碼創(chuàng)建了一個(gè)名稱為 foo 的數(shù)據(jù)卷,該數(shù)據(jù)卷對(duì)應(yīng)著主機(jī)上的 /var/lib/docker/volumes/foo/_data 物理目錄风纠。
$ docker volume create foo
docker create -v / docker run -v
使用 docker create -v
或 docker run -v
命令創(chuàng)建容器時(shí)况鸣,可以使用 -v
參數(shù)將容器的指定目錄掛載到指定的數(shù)據(jù)卷。以下代碼創(chuàng)建了一個(gè)容器 db1 竹观,然后將容器的 /data 目錄掛載到已經(jīng)存在的名為 foo 的數(shù)據(jù)卷镐捧。
$ docker create -v foo:/data --name db1 centos
以下代碼創(chuàng)建了一個(gè)名為 db2 的容器,然后將容器的 /data 目錄掛載到名為 bar 的數(shù)據(jù)卷栈幸,由于 bar 數(shù)據(jù)卷不存在愤估,所以在創(chuàng)建容器的時(shí)候會(huì)先創(chuàng)建一個(gè)名為 bar 的數(shù)據(jù)卷,然后將 /data 目錄掛載到 bar 數(shù)據(jù)卷速址,該數(shù)據(jù)卷對(duì)應(yīng)著主機(jī)上的 /var/lib/docker/volumes/bar/_data 物理目錄玩焰。
$ docker create -v bar:/data --name db2 centos
以下代碼創(chuàng)建了一個(gè)名為 db3 的容器,然后將容器的 /data 目錄掛載到匿名的數(shù)據(jù)卷芍锚。創(chuàng)建容器的時(shí)候會(huì)先創(chuàng)建一個(gè)名為隨機(jī)字符串的數(shù)據(jù)卷昔园,然后將 /data 目錄掛載到該數(shù)據(jù)卷,該數(shù)據(jù)卷對(duì)應(yīng)著主機(jī)上的 /var/lib/docker/volumes/隨機(jī)字符串/_data 物理目錄并炮。
$ docker create -v /data --name db3 centos
以下代碼創(chuàng)建了一個(gè)名為 db4 的容器默刚,然后將容器的 /data 目錄掛載到指定的主機(jī)目錄的絕對(duì)路徑,這個(gè)主機(jī)目錄并不是數(shù)據(jù)卷逃魄,因此通過(guò)數(shù)據(jù)卷命令 docker volume
無(wú)法管理該主機(jī)目錄荤西。
$ docker create -v /Users/yumanli/Desktop/data:/data --name db4 centos
可以使用 :ro
來(lái)綁定只讀的數(shù)據(jù)卷,只能綁定具名數(shù)據(jù)卷或者主機(jī)目錄伍俘。
$ docker create -v foo:/data:ro --name db1 centos
$ docker create -v /Users/yumanli/Desktop/data:/data:ro --name db4 centos
不能使用 :ro
來(lái)綁定匿名數(shù)據(jù)卷邪锌,以下代碼會(huì)報(bào)錯(cuò)。
$ docker create -v /data:ro --name db3 centos
docker volume ls
使用 docker volume ls
命令查看所有的數(shù)據(jù)卷癌瘾。
$ docker volume ls
DRIVER VOLUME NAME
local 6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09
local bar
local foo
使用 docker volume ls -f dangling=true
命令查看沒(méi)有被掛載到容器的數(shù)據(jù)卷觅丰。
$ docker volume create baz
$ docker volume ls -f dangling=true
DRIVER VOLUME NAME
local baz
docker volume inspect
使用 docker volume inspect
命令查看數(shù)據(jù)卷的信息,Name
字段為數(shù)據(jù)卷的名字妨退,Mountpoint
字段為數(shù)據(jù)卷掛載的主機(jī)目錄妇萄。
$ 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
命令刪除數(shù)據(jù)卷蜕企,該命令只能刪除沒(méi)有被掛載到容器的數(shù)據(jù)卷。
$ docker volume rm baz
對(duì)于已經(jīng)被掛載到容器的數(shù)據(jù)卷冠句,必須先刪除相關(guān)容器轻掩,再刪除數(shù)據(jù)卷。db1 容器掛載了 foo 數(shù)據(jù)卷懦底,要想刪除 foo 數(shù)據(jù)卷放典,必須先刪除 db1 容器。
$ docker rm db1
$ docker volume rm foo
可以使用 docker rm -v
命令基茵,在刪除容器的同時(shí)刪除該容器掛載的數(shù)據(jù)卷。該命令只能刪除匿名數(shù)據(jù)卷(名字為一串隨機(jī)字符串的數(shù)據(jù)卷)壳影,不會(huì)刪除具名數(shù)據(jù)卷拱层。db2 容器掛載了 bar 數(shù)據(jù)卷,db3 容器掛載了匿名數(shù)據(jù)卷 6cda7f4532a18c226ae419cee91c7d08ca6fe6e409914b25f368b8edea641a09宴咧,使用以下命令不會(huì)刪除 bar 數(shù)據(jù)卷根灯。
$ docker rm -v db2 db3
$ docker volume ls
local bar
docker volume prune
使用 docker volume prune
命令刪除所有沒(méi)有被掛載到容器的數(shù)據(jù)卷,不管該數(shù)據(jù)卷是具名的還是匿名的掺栅。
$ 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-from
或 docker run --volumes-from
命令創(chuàng)建容器時(shí)烙肺,可以使用 --volumes-from
參數(shù)使得新創(chuàng)建的容器與已有的容器共享數(shù)據(jù)卷。
以下代碼將 db2 容器的 /data 目錄與 db1 容器的 /data 目錄綁定到同一個(gè)具名數(shù)據(jù)卷 foo (對(duì)應(yīng)著主機(jī)上的同一個(gè)物理目錄 /var/lib/docker/volumes/foo/_data)氧卧,因此 db1 和 db2 容器可以共享數(shù)據(jù)桃笙。
$ docker create -v foo:/data --name db1 centos
$ docker create --volumes-from db1 --name db2 centos
以下代碼可以通過(guò)另一種方式實(shí)現(xiàn)同樣的功能。首先創(chuàng)建一個(gè)具名數(shù)據(jù)卷 foo沙绝,然后分別創(chuàng)建兩個(gè)容器 db1 和 db2搏明,并綁定到這個(gè)數(shù)據(jù)卷 foo,這樣也可以實(shí)現(xiàn)多個(gè)容器共享數(shù)據(jù)卷闪檬。
$ docker volume create foo
$ docker create -v foo:/data --name db1 centos
$ docker create -v foo:/data --name db2 centos
如果一些數(shù)據(jù)星著,比如配置文件、數(shù)據(jù)文件等粗悯,要在多個(gè)容器之間共享虚循,一種常見(jiàn)的做法是創(chuàng)建一個(gè)數(shù)據(jù)容器,其他容器與之共享 volume样傍。
以下代碼先創(chuàng)建了一個(gè)名為 db 的容器作為數(shù)據(jù)容器横缔,將該容器 /data 目錄掛載到一個(gè)匿名數(shù)據(jù)卷(也可以掛載到具名數(shù)據(jù)卷或主機(jī)目錄)。然后又創(chuàng)建了 db1 和 db2 兩個(gè)容器铭乾,并通過(guò) --volumes-from
參數(shù)指定 db1 和 db2 容器與 db 容器共享數(shù)據(jù)卷剪廉,這樣 db 容器的 /data 目錄、db1 容器的 /data 目錄和 db2 容器的 /data 目錄都掛載到一個(gè)相同的數(shù)據(jù)卷(對(duì)應(yīng)著主機(jī)上的同一個(gè)物理目錄)炕檩,因此他們可以共享數(shù)據(jù)斗蒋。
$ 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 參數(shù)可以事先指定某個(gè)鏡像掛載的數(shù)據(jù)卷捌斧。
FROM centos
VOLUME ["/data"]
使用 docker build
命令基于該 Dockerfile 創(chuàng)建一個(gè)鏡像。
$ 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
通過(guò)該鏡像創(chuàng)建容器的時(shí)候泉沾,就不需要通過(guò) -v
參數(shù)掛載數(shù)據(jù)卷了捞蚂,該容器會(huì)使用 Dockerfile 文件的 VOLUME 參數(shù)掛載數(shù)據(jù)卷。
$ 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
命令創(chuàng)建容器可以在 Dockerfile 文件的 VOLUME 參數(shù)基礎(chǔ)上掛載新的數(shù)據(jù)卷跷究。
$ 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": ""
}
]