如何在Docker容器和主机之间共享数据

175 阅读9分钟

如何在Docker容器和主机之间共享数据

Docker之所以出色,原因之一是它能够将一个应用程序容器化,而不需要在你的本地计算机上安装额外的依赖项。然而,Docker运行在一个虚拟化架构上。这为远离主机的应用程序的运行创造了一个隔离的环境。

Docker引擎的作用是将主机上的资源分配给虚拟化隔离的应用程序。一旦这种应用程序被容器化,应用程序的虚拟化数据就与主机隔离。这意味着当你虚拟化一个应用程序时,它的所有数据将被托管在dockerize容器中。在这种情况下,主机和应用程序是在不同的基础设施上运行。

有时,你可能希望你的虚拟容器化应用程序直接从主机上分享数据和文件。

默认情况下,容器内产生的所有文件都保存在一个可写的容器层上。一旦容器不再运行,数据就不会持久化。容器的可写层与容器所执行的主机紧密相连。因此,数据不能轻易地转移到另一个地方。

Docker为容器提供了两种方法来保存主机系统上的文件,这样即使在容器关闭后,这些文件也是持久的。它们是Docker绑定挂载。

本博客将教你如何在Docker容器化应用和主机之间共享数据。

前提条件

本指南是关于Docker的。关于如何使用Docker来运行应用程序的预先知识是必不可少的。

设置Docker

  • 首先,确保你已经在你的电脑上下载并安装了Docker。通过运行来检查。
docker --version
  • 接下来,你需要提取Nginx镜像。前往终端,使用下面的命令从Docker中心拉出Nginx镜像。
docker pull nginx

你可以使用命令docker image ls ,检查镜像是否被下载,镜像将被列在你的终端上。

nginx-docker-image

这表明带有最新标签的Nginx已经从Docker hub成功下载。因此,我们可以用它来构建一个Docker容器,用来执行这个镜像。

使用绑定挂载

默认情况下,Docker将应用程序作为无状态运行。它发送了一个可写层,以允许应用程序的写访问,但你在那里写的一切,一旦容器停止,就会被删除。这意味着可写层的访问并不总是可靠的。因此,Docker使用不同的方法,如绑定挂载、卷和内存选项来临时管理应用程序的文件系统。

绑定挂载的作用是在容器内暴露主机系统上的文件或目录。这是一种强大的技术,可以从你的容器内访问主机上的文件。

因为数据存储在主机上,所以当容器终止时,它不会丢失。由于这些数据存储在主机上,你必须知道你希望在容器中挂载的主机上的正确路径。

这将有利于你的开发,因为你将不必重建镜像来访问新的源代码。你对你的源代码进行修改,而这些修改会立即反映在挂载的容器上。

为了使用bind mount,我们将按照以下步骤进行。

第1步:让我们制作一个目录,在那里我们将与容器一起挂载

运行下面的命令来创建一个目录。

mkdir -p /tmp/nginx/html

第2步:使用Nginx镜像构建并运行该容器

使用我们拉来的Nginx镜像,我们将创建一个Docker容器,它将。

  • 使用-t -d ,在后台运行一个容器。
  • 使用-P 来设置端口映射。
  • 使用-v ,设置用于挂载的卷,这是我们在上一步创建的卷,是Nginx文件的位置。
  • 使用--name ,设置容器的名称。
  • 使用nginx:latest ,设置Nginx镜像。
docker run -t -d -P -v /tmp/nginx/html:/usr/share/nginx/html --name nginxcont nginx:latest

运行上述命令后,使用命令检查运行中的容器。

docker container ls

bind-mount-containers

第3步:获取你的IP地址

要获得你的IP地址,请键入下面的命令。

ifconfig

你可以通过在PORTS 列下检查,或者直接运行run docker container ls 命令,从我们在前面过程中创建的容器中获得你的端口号。这将得到分配给我们正在使用的容器的端口号。

进入你的浏览器,在你的标签中键入以下URL。http://<your_ip_address>:<your_port>.由于我们在目录中没有任何HTML文件,你的内容应该类似于。

bind-mount-default

第4步:测试

在你的当前目录中,创建一个index.html 文件,并添加以下几行代码。

<!DOCTYPE html>
<html>

<head>
   <title>Welcome to nginx!</title>
   <style>
     body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
     }
   </style>
</head>

<body>
   <h1>Welcome to nginx! Edited</h1>
   <p>
     If you see this page, the Nginx web server is successfully installed and working. Further configuration is required.
   </p>

   <p>
     For online documentation and support please refer to
     <a href="http://nginx.org/">nginx.org</a>.<br />
     Commercial support is available at
     <a href="http://nginx.com/">nginx.com</a>.
   </p>

   <p><em>This file is edited</em></p>
</body>

</html>

我们将把这个文件从主机复制到我们之前创建的Docker容器的安装文件夹中。使用这个命令来复制该文件。

cp index.html /tmp/nginx/html

运行上述命令后,刷新你的浏览器标签,你会看到新的内容。

现在我们来更新这个文件。首先,使用下面的命令进入这个文件所在的目录。

cd /tmp/nginx/html

现在,使用你的代码编辑器,修改该文件并保存它。如果你刷新浏览器标签,你应该能够直观地看到你所做的修改。你现在已经探索了如何使用绑定挂载将文件从主机共享到Docker容器。

使用卷挂载

要使用卷挂载在主机和容器之间共享数据,请遵循以下步骤。

第1步:创建一个卷

首先使用这个命令创建一个卷。

docker volume create simplevol

以确认卷是否被创建,运行该命令。

docker volume ls

volumes

第2步:容器映射

运行一个Docker容器来映射你上面创建的卷。我们将使用以下说明。

  • -t -d 在后台运行一个容器。
  • -P 设置一个端口映射。
  • --name 来设置容器的名称。
  • -v 来设置卷。通过卷,我们将其设置为Nginx文件的存储位置,这样我们就可以编辑它们并看到它们的运行情况。
  • 使用Nginx镜像与nginx:latest ,创建一个容器。

现在运行这个命令来执行上述参数。

docker run -t -d -P --name nginxcont1 -v simplevol:/usr/share/nginx/html nginx:latest

容器已经设置好,应该正在运行。要检查容器的状态,请运行该命令。

docker container ls

containers

第3步:获取主机的IP地址

通过运行ifconfig命令获得你的主机的IP地址。

ifconfig

你的IP地址将在inet 参数上。对于我们的情况,它是172.19.0.1。你将在你的响应中找到它,如下所示。

ip-address

  • PORTS 栏中,从上一步检查容器状态的过程中获得容器所映射的端口号。

  • 有了IP地址和端口号,你现在可以去你的浏览器,打开一个标签,并键入以下内容。http://<your_ip_address>:<your_port>.

你的页面应该类似于以下内容。

default-nginx-page

第4步:测试

首先,将Nginxindex.html 从容器中复制到你的主机上。要做到这一点,键入以下命令。

docker cp nginxcont1:/usr/share/nginx/html/index.html index.html

用你的代码编辑器打开该文件,按如下方式更新并保存。

<!DOCTYPE html>
<html>
   <head>
     <title>Welcome to nginx!</title>
     <style>
       body {
         width: 35em;
         margin: 0 auto;
         font-family: Tahoma, Verdana, Arial, sans-serif;
       }
     </style>
   </head>
   <body>
     <h1>Welcome to nginx! Edited</h1>
     <p>
       If you see this page, the Nginx web server is successfully installed and working. Further configuration is required.
     </p>

     <p>
       For online documentation and support please refer to
       <a href="http://nginx.org/">nginx.org</a>.<br />
       Commercial support is available at
       <a href="http://nginx.com/">nginx.com</a>.
     </p>

     <p><em>This file is edited</em></p>
   </body>
</html>

通过运行该命令,将编辑好的文件从你的电脑推送到Docker容器中。

docker cp index.html nginxcont1:/usr/share/nginx/html

如果你刷新之前打开的标签,内容应该已经更新,以反映添加的变化。

updated-nginx-page

到目前为止,你已经能够运行一个带有卷装载的容器,将文件从主机复制到Docker容器,反之亦然。有了卷挂载,即使我们删除了当前的容器,文件也会保持更新。为了验证这一点,我们将。

  • 首先,停止当前的容器。
docker stop nginxcont1
  • 然后,使用命令启动一个不同的容器挂载到同一个卷。
docker run -t -d -P --name nginxcont2 -v simplevol:/usr/share/nginx/html nginx:latest
  • 用你的IP地址和新创建的容器的端口,从浏览器访问它。你会看到,内容是更新的。这是因为我们把它挂载到了一个卷上。

现在你已经了解了卷的挂载及其数据的持久性。

顺便提一下,当你使用docker-compose运行你的docker化应用程序时,也会用到卷。当你写一个docker-compose文件时,你可以指定卷,而卷的路径将在建立应用容器时自动创建。

下面是一个docker-compose.yml文件的例子,它可以用来对Mongo数据库进行dockerize。

version: '3.8'
services:
 mongo:
   image: mongo:4.2.8
   ports:
     - 27017:27017
   volumes:
     - mongodb:/data/db

在上面的例子中,数据库容器运行在一台主机上。该容器有一个虚拟文件系统,数据通常存储在那里,没有持久性。

如果我们要停止并重启容器,这个虚拟文件系统中的数据就会消失,它将从一个全新的状态开始。但是由于我们在这个docker-compose文件中添加了volumes ,应用程序在数据库中的变化将被保存。

来自主机文件系统的目录被挂载到Docker虚拟文件系统的一个文件夹中。当容器向其文件系统发布时,它将被即时复制并写入主机文件系统目录,反之亦然。

当容器重新启动其虚拟文件系统时,它会自动从主机上获得数据,因为每次重新启动容器时,数据仍然存在。

总结

我们已经介绍了如何在Docker容器和主机之间共享数据。这些过程是直接实现的。

如果你使用的是Docker卷,你可以使用同样的方法,使用数据卷在Docker环境中运行的不同容器之间共享数据。