关于Docker绑定挂载的实例

115 阅读2分钟

让我们来看看Docker中的绑定挂载,以及持久化数据如何与这些挂载一起工作。绑定挂载与[Docker卷]有点不同,但使用它们的语法却很相似。绑定挂载是非常酷的,因为它允许本地开发的文件在容器中实时更新。从技术上讲,绑定挂载是将主机的文件或目录映射到容器的文件或目录中。所以你可以只指定一个文件或整个目录。在后台,就像主机上的位置和容器上的位置都指向磁盘上的同一个位置。


绑定挂载实例一

首先,让我们在主机上创建一个目录。我们将该目录命名为host,然后cd进入该目录。

PS C:\code> mkdir host
PS C:\code> cd host
PS C:\code\host>

好的,我们有一个空的目录 **host**的空目录,我们现在正在其中工作。现在让我们从alpine镜像中运行一个容器,并在主机和容器之间设置一个绑定挂载。绑定挂载的语法是蓝色的,左边的pwd表示使用当前工作目录。:的左边是{pwd}表示使用当前工作目录。 **`:`**的左边是{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的闪屏。该容器没有使用主机上的任何文件。

docker bind mount example

现在,让我们运行第二个名为nginx2的容器,但这次我们要使用一个Bind Mount。同样,命令中指定绑定挂载的部分是蓝色的。

docker> docker container run -d --name nginx2 -p 80:80 -v ${pwd}:/usr/share/nginx/html nginx
933bd7033cc370133f4b4e5475036610589e9424248d212d7d812f1c4ef7b852

我们现在有两个网络服务器在运行。第一个使用80端口,没有绑定挂载。第二个使用8080端口,并使用了绑定挂载。我们可以看到,第二个网络服务器正在使用容器中的localhost的文件。非常酷

web server 1 and 2 in containers

这样做的好处是,主机上的变化会实时地反映到容器中。让我们对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>

重新加载连接到容器上的浏览器,瞧,更新马上就发生了。

docker bind mounts are great