让我们来看看Docker中的绑定挂载,以及持久化数据如何与这些挂载一起工作。绑定挂载与[Docker卷]有点不同,但使用它们的语法却很相似。绑定挂载是非常酷的,因为它允许本地开发的文件在容器中实时更新。从技术上讲,绑定挂载是将主机的文件或目录映射到容器的文件或目录中。所以你可以只指定一个文件或整个目录。在后台,就像主机上的位置和容器上的位置都指向磁盘上的同一个位置。
绑定挂载实例一
首先,让我们在主机上创建一个目录。我们将该目录命名为host,然后cd进入该目录。
PS C:\code> mkdir host
PS C:\code> cd host
PS C:\code\host>
好的,我们有一个空的目录 **host**的空目录,我们现在正在其中工作。现在让我们从alpine镜像中运行一个容器,并在主机和容器之间设置一个绑定挂载。绑定挂载的语法是蓝色的,左边的{pwd},意思是使用当前工作目录作为主机目录。右边的 **:**的右边是我们要映射到的容器中的目录。
PS C:\code\host> docker container run -it --name alpine -v ${pwd}:/container alpine
看看运行中的容器是如何立即拥有一个名为container的目录的。在Docker中创建绑定挂载时,如果你在容器中指定的目录还不在那里,它就会为你创建。
/ # ls -l
total 56
drwxr-xr-x 2 root root 4096 Oct 21 09:23 bin
drwxrwxrwx 1 root root 4096 Oct 23 16:24 container
drwxr-xr-x 5 root root 360 Oct 23 16:29 dev
drwxr-xr-x 1 root root 4096 Oct 23 16:29 etc
drwxr-xr-x 2 root root 4096 Oct 21 09:23 home
drwxr-xr-x 7 root root 4096 Oct 21 09:23 lib
drwxr-xr-x 5 root root 4096 Oct 21 09:23 media
drwxr-xr-x 2 root root 4096 Oct 21 09:23 mnt
drwxr-xr-x 2 root root 4096 Oct 21 09:23 opt
dr-xr-xr-x 176 root root 0 Oct 23 16:29 proc
drwx------ 1 root root 4096 Oct 23 16:29 root
drwxr-xr-x 2 root root 4096 Oct 21 09:23 run
drwxr-xr-x 2 root root 4096 Oct 21 09:23 sbin
drwxr-xr-x 2 root root 4096 Oct 21 09:23 srv
dr-xr-xr-x 11 root root 0 Oct 23 16:29 sys
drwxrwxrwt 2 root root 4096 Oct 21 09:23 tmp
drwxr-xr-x 7 root root 4096 Oct 21 09:23 usr
drwxr-xr-x 12 root root 4096 Oct 21 09:23 var
换到容器目录中,列出文件,我们看到没有任何文件。
/ # cd container
/container # ls
/container #
打开一个新的终端实例,因为现在的实例已经连接到正在运行的容器上了。导航到我们已经创建的主机目录。注意,它是空的。
PS C:\code\host> ls
PS C:\code\host>
在主机目录下的主机上创建一个文件,注意它现在存在于该主机目录中。
PS C:\code\host> echo 'Created on host machine!' >> file1.txt
PS C:\code\host> ls
Directory: C:\code\host
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/23/2020 12:37 PM 54 file1.txt
导航回到仍然连接到运行中的容器的原始终端。列出该容器目录中的文件。
/container # ls
file1.txt
/container # cat file1.txt
Created on host machine!
哇!由于我们设置的绑定挂载,该文件存在于容器中。这真是太酷了。现在让我们在容器上创建另一个文件,看看会发生什么。
/container # echo 'File created on container!' > file2.txt
/container # ls
file1.txt file2.txt
回到在主机上工作的终端,我们可以列出文件,我们可以看到,在容器上创建的文件现在也存在于主机中。
PS C:\code\host> ls
Directory: C:\code\host
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/23/2020 12:37 PM 54 file1.txt
-a---- 10/23/2020 12:42 PM 27 file2.txt
PS C:\code\host> cat file2.txt
File created on container!
这真的很有趣,你可以开始看到在使用容器时,这对你来说真的很有好处。你真的可以把任何你想要的东西从主机上映射到容器中。当你开始谈论主机上的开发时,这个概念是非常有帮助的,同时在容器上运行服务,访问你可能正在主机上编辑的文件。当你对主机上的文件进行修改时,这些都会实时反映在容器中。
绑定挂载实例二
第一个例子是我们可以做到的最基本的,只是为了展示绑定挂载的语法和它是如何工作的。现在让我们看一个例子,在容器中使用一个Nginx网络服务器,它能够提供你在本地机器上编辑的HTML文件。把这个index.html文件放在主机目录下,像这样。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/css/bootstrap.min.css"
integrity="sha384-DhY6onE6f3zzKbjUPRc2hOzGAdEf4/Dz+WJwBvEYL/lkkIsI3ihufq9hk9K4lVoK"
crossorigin="anonymous"
/>
<title>Hello, world!</title>
</head>
<body class="container mt-5">
<div class="card">
<div class="card-body">
<h1 class="card-title">Hello World!</h1>
<h3 class="card-subtitle mb-2 text-muted">Docker Bind Mounts</h3>
<p class="card-text">
Now we know how to use Docker Bind Mount with the Nginx web server.
</p>
</div>
</div>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper.js -->
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/js/bootstrap.bundle.min.js"
integrity="sha384-BOsAfwzjNJHrJ8cZidOg56tcQWfp6y72vEJ8xQ9w6Quywb24iOsW913URv1IS4GD"
crossorigin="anonymous"
></script>
<!-- Option 2: Separate Popper.js and Bootstrap JS
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/js/bootstrap.min.js" integrity="sha384-5h4UG+6GOuV9qXh6HqOLwZMY4mnLPraeTrjT5v07o347pj6IkfuoASuGBhfDsp3d" crossorigin="anonymous"></script>
-->
</body>
</html>
确认我们在主机目录下有一个新文件。
PS C:\code\host> ls
Directory: C:\code\host
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/23/2020 1:21 PM 1758 index.html
首先,让我们运行一个没有绑定挂载的Nginx容器,看看它能给我们带来什么。我们可以把这个容器命名为nginx1。
PS C:\code\host> docker container run -d --name nginx1 -p 80:80 nginx
c659e507bbc714ec3beb4e78acac2f232f9d9753614286dae143a0cc1b6a3817
在浏览器中访问该容器,会看到Nginx的闪屏。该容器没有使用主机上的任何文件。

现在,让我们运行第二个名为nginx2的容器,但这次我们要使用一个Bind Mount。同样,命令中指定绑定挂载的部分是蓝色的。
docker> docker container run -d --name nginx2 -p 80:80 -v ${pwd}:/usr/share/nginx/html nginx
933bd7033cc370133f4b4e5475036610589e9424248d212d7d812f1c4ef7b852
我们现在有两个网络服务器在运行。第一个使用80端口,没有绑定挂载。第二个使用8080端口,并使用了绑定挂载。我们可以看到,第二个网络服务器正在使用容器中的localhost的文件。非常酷

这样做的好处是,主机上的变化会实时地反映到容器中。让我们对index.html的源代码做一个修改。注意被改变的那一行。
<div class="card">
<div class="card-body">
<h1 class="card-title">Have A Great Day!</h1>
<h3 class="card-subtitle mb-2 text-muted">Docker Bind Mounts</h3>
<p class="card-text">
Now we know how to use Docker Bind Mount with the Nginx web server.
</p>
</div>
</div>
重新加载连接到容器上的浏览器,瞧,更新马上就发生了。
