Skip to content

Commit 7f41f6e

Browse files
committed
add docker volumes
1 parent 34b3617 commit 7f41f6e

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

docker-indepth-volumes-cn.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
##深入Docker之Volumes
2+
3+
【编者的话】这篇文章是[深入理解Docker Volume](http://dockerone.com/article/128)的延伸阅读篇,作者通过对比Dockerfile中的VOLUME指令跟命令行docker run 中```-v```标志深入分析了Volume的原理以及与容器之间的联系。
4+
5+
人们使用Docker最常见的障碍之一,还有我看大量的Docker支持渠道也确实很容易出现该问题,那就是Volumes的使用。
6+
7+
因此,让我们来仔细看一下Docker Volume是如何工作的。
8+
9+
首先,让我们来驱散第一个最常见的误解:
10+
11+
Docker Volumes是为了持久性。
12+
13+
这可能来自于容器不是持久的想法,这样确实是不对的。容器的持久直到您删除他们,并且你只能这样做:
14+
```docker rm my_container
15+
```
16+
17+
如果您没有键入此命令,那么你的容器仍然存在并将继续存在,它可以启动、停止等。如果你没有看到你的容器,你应该运行此命令:
18+
```docker ps -a```
19+
20+
```docker ps```永远只显示正在运行的容器,但是一个容器可以是停止状态,在这种情况下,上面的命令会显示你所有的容器无论状态如何。```docker run ...```其实是一个多命令集合,它会创建一个新的容器,然后启动它。
21+
22+
因此,再次声明:Volume不是为了持久。
23+
24+
###什么是Volume
25+
26+
Volumes使创建它们的容器使用寿命与在它们中储存数据的寿命解耦。这使得它你可以```docker rm my_container```后你的数据不会被删除。
27+
28+
Volume可以用以下两种方式创建:
29+
30+
- 在Dockerfile中指定```VOLUME /some/dir```
31+
- 当执行```docker run -v /some/dir```命令来指定
32+
33+
无论哪种方式,这两样东西都做了同样的事情。它告诉Docker在主机上创建一个目录(默认情况下是```/var/lib/docker```),然后将其挂载到您指定的路径(例子中是:```/some/dir```)。当您删除使用该Volume的容器,该Volume本身将一直存在下去。
34+
35+
如果在容器中不存在指定的路径,那么此目录将被自动创建。
36+
37+
你能告诉Docker同时删除容器和其Volume:
38+
```docker rm -v my_container
39+
```
40+
41+
有时候,你的主机已经有了要在容器中使用的目录,CLI(命令行界面)多了一种选择来指定这些:
42+
```docker run -v /host/path:/some/path ...
43+
```
44+
45+
这明确地告诉Docker使用指定的主机路径来代替Docker自己创建的根路径并挂载到容器内指定的路径(以上例子为:```/some/path```)。值得注意,这样做也可以是一个文件来代替目录。在Docker术语中这通常被称为bind-mounts(虽然技术层面上是这样讲的,但是实际的感官是所有的Volumes都是bind-mounts的)。如果主机上的路径不存在,目录将自动在给定的路径中创建。
46+
47+
对待Bind-mount Volumes跟一个“正常”的Volume有点点不同,它的特点是不会修改主机上那些并非Docker自身创建的东西:
48+
49+
1. 一个“正常”的Volume,Docker会自动复制在指定的Volume路径的数据(如上边示例:```/some/path```)到由Docker创建新的目录下,如果是“bind-mount” Volume就不会发生这种情况。
50+
2. 当你执行```docker rm -v my_container```命令给“bind-mount” Volume的容器,“bind-mount” Volumes不会被删除。
51+
52+
容器也可以与其他容器共享Volumes。
53+
```docker run --name my_container -v /some/path ...
54+
docker run --volumes-from my_container --name my_container2 ...```
55+
56+
上面的命令将告诉Docker从第一个容器挂载相同的Volumes到第二个容器。它有效地共享数据在两个容器之间。
57+
58+
如果你执行```docker rm -v my_container```命令,而上方的第二容器依然存在,Volumes不会被删除,而且它永远不会被删除除非你执行```docker rm -v my_container2```删除第二个容器,。
59+
60+
###Dockerfiles里的VOLUME
61+
正如前面提到的,Dockerfile中的VOLUME声明中做同样的事情类似```docker run```命令里的```-v```标志(除了你不能在Dockerfile指定主机路径)。它只是恰巧发生了,也正因为如此,构建镜像时可以得到惊奇的效果。
62+
63+
在Dockerfile中的每个命令创建一个新的用于运行指定命令的容器,并将容器提交回镜像,每一步都是在前一步的基础上构建。因此在Dockerfile中```ENV FOO=bar```等同于:
64+
```cid=$(docker run -e FOO=bar <image>)
65+
docker commit $cid
66+
```
67+
68+
下面让我们来看看这个Dockerfile的例子发生了什么:
69+
```FROM debian:jessie
70+
VOLUME /foo/bar
71+
RUN touch /foo/bar/baz
72+
```
73+
74+
```docker build -t my_debian .
75+
```
76+
77+
我们期待的是Docker创建名为my_debian并且Volume是``` /foo/bar```的镜像,以及在```/foo/bar/baz```下添加了一个空文件,但是让我们看看等同的CLI命令行实际上做了哪些:
78+
```cid=$(docker run -v /foo/bar debian:jessie)
79+
image_id=$(docker commit $cid)
80+
cid=$(docker run $image_id touch /foo/bar/baz)
81+
docker commit $(cid) my_debian
82+
```
83+
84+
它并不是确切地发生了这些,但是非常类似。
85+
86+
那么,这里发生的是在```/foo/bar```里的任何东西存在之前,Volume就被创建,因此我们每次从这个镜像启动一个容器,会有一个空的```/foo/bar```目录。它之所以发生如前所述,Dockerfile中每个命令都是创建一个新容器。这意味着,同时也创建了一个新的Volume。由于举例Dockerfile中是先指定Volume的,当执行```touch /foo/bar/baz```命令的容器创建时,一个Volume被挂载到了```/foo/bar```,然后```baz```才能被写入此Volume,而不是实际的容器或镜像的文件系统内。
87+
88+
所以,牢记Dockerfile中```VOLUME```声明的位置,因为它在你的镜象内创建了不可改变的目录。
89+
90+
```docker cp```[#8509](https://github.com/docker/docker/pull/8509)),```docker commit``````docker export```还不支持Volumes(在文章截稿时)。
91+
92+
目前,在容器的创建/销毁期间来管理Volumes(创建/销毁)是唯一的方式,这有点古怪,因为Volumes是为了分离容器内的数据与容器的生命周期。Docker团队正在处理,但尚未合并([#8484](https://github.com/docker/docker/pull/8484))。
93+
94+
如果您想了解Docker Volume的更多功能,[请这边走](https://github.com/cpuguy83/docker-volumes)
95+
96+
**原文链接:[Docker In-depth: Volumes](http://container42.com/2014/11/03/docker-indepth-volumes/)(翻译:[田浩](https://github.com/llitfkitfk)**

0 commit comments

Comments
 (0)