Docker動手教程4.1:容器存儲1

内容摘要

  1. 容器挂载主机目录
  2. 容器挂载主机文件

应用程序往往会使用数据库或者文件系统保存数据.比如web应用,需要保存静态网页和用户数据。对容器而言,里面运行的应用程序同样有持久化数据的需要,容器启动时需要加载数据,销毁时需要保留数据。本节带大家深入探讨容器如何使用存储。

容器挂载主机目录

容器可以直接挂载主机上的目录

准备容器环境,在根目录下创建test文件夹,在其下面创建index.html文件,内容如下:

 
 

this is docker volume!

Docker动手教程4.1:容器存储1

使用 httpd:2.4 容器,将主机test目录挂载到容器目录,运行容器,命令如下:

docker run -d -p 80:80 -v /root/test:/usr/local/apache2/htdocs http:2.4
Docker动手教程4.1:容器存储1

参数 -p 80:80 :建立容器80端口和主机80端口映射,网络部分会在后面深入分析,这里只简单提一下。

-v:表示卷映射,用法是:-v 主机目录:容器目录。

容器起来后,使用如下命令访问httpd:

Docker动手教程4.1:容器存储1

可以看到 index.html 文件中的内容。

进入容器中的挂载目录看看该文件是否在容器可以访问:

Docker动手教程4.1:容器存储1

可以看到在容器中可以访问index.html文件。

如果我们在test文件夹再增加文件 welcome.html ,这样test下就有两个文件了,welcome.html文件内容如下:

 
 

welcome to docker volume!

Docker动手教程4.1:容器存储1

运行容器,并使用curl访问html文件,命令如下:

docker run -d -p 80:80 -v /root/test:/usr/local/apache2/htdocs http:2.4
curl 127.0.0.1:80
curl 127.0.0.1:80/welcome.html
Docker动手教程4.1:容器存储1

访问成功,如果不指定具体 html 文件,curl默认访问 index.html 文件。

进入容器中,也可以看到 html 文件存在挂载目录下;

如果在主机修改 index.html 文件,那么容器中的文件会相应修改吗?

修改index.html文件内容如下:

 
 

this is docker volume! hello docker volume!

使用curl访问,并进入容器查看文件,如下图:

Docker动手教程4.1:容器存储1

可以看到,容器中的index.html文件内容也更改了。

现在反过来,我们在容器中修改index.html文件,然后在主机中观察:

我们将index.html内容改为:

updated index.
Docker动手教程4.1:容器存储1

第1步:进入容器

第2步:修改index.html文件

第3步:使用exit离开容器

第4步:在主机上查看index.html文件发现内容已经变更。

在上面的操作中,我们可以在容器中修改index.html文件是因为我们有读写该文件的权限。

容器在挂载存储的时候可以指定读写权限,默认可读可写,也可以指定为只读。权限控制能提高数据的安全性。

注意:该权限只是约束在容器中对文件的操作,没有约束主机的操作。

下面我们重新运行上面的容器,并设置存储读写权限为只读,命令为:

docker run -d -p 80:80 -v /root/test:/usr/local/apache2/htdocs:ro http:2.4
Docker动手教程4.1:容器存储1

在 -v 参数目录后面新加了 :ro,表示只读。

进入容器中,修改index.html文件:

Docker动手教程4.1:容器存储1

可以看到修改失败,提示:Read-only file system。

在主机中修改:

Docker动手教程4.1:容器存储1

先离开容器,之后修改文件,查看,文件已经修改了。

结论:只能控制容器修改文件的权限,不能控制主机修改文件的权限。

使用 docker inspect 观察容器:

Docker动手教程4.1:容器存储1

上图截取了Mounts部分,可以看到这里记录了存储映射信息。

dockers也提供了一个命令查询容器存储卷,命令为:docker volume ls

Docker动手教程4.1:容器存储1

查询数据为空,该命令没有查到数据。

可见该命令有缺陷,说明这种挂载方式,无法使用该命令查询。

我们测试下删除操作,分别在主机上删除和在容器中删除index.html。

Docker动手教程4.1:容器存储1

在主机上删除index.html文件后,使用curl访问,出现404 Not Found错误。

进入容器查看文件是否存在:

Docker动手教程4.1:容器存储1

可以看到index.html不存在;

在容器中删除文件的情景是一样的,大家可以自行测试下。

问题:如果主机目录和容器挂载目录下有同名的文件,那么会不会覆盖呢?

其实,在httpd容器中,/usr/local/apache2/htdocs目录下存在一个index.html文件,我们主机test目录下也有index.html文件,使用curl访问返回信息却是我们主机的文件内容,可见这里出现了文件覆盖,即主机的文件覆盖了容器的同名文件。

我们先不挂载主机目录,运行httpd容器,使用命令:

docker run -d -p 80:80 httpd:2.4
Docker动手教程4.1:容器存储1

可以看到在容器中存在index.html文件,输出的内容是 It works!

下面我们重新运行容器,并挂载存储,命令参考上面

Docker动手教程4.1:容器存储1

可以看到,index.html文件的内容发生了变化,可见原先的文件已经被覆盖了。

容器挂载主机文件

如果我们不想原先的index.html文件被覆盖,该如何做呢?

前面我们在挂载的时候,使用了目录挂载,实际上可以文件挂载,这样就能避免文件被覆盖。

运行容器,命令如下:

docker run -d -p 80:80 -v /root/test/index.html:/usr/local/apache2/htdocs/myindex.html httpd:2.4
Docker动手教程4.1:容器存储1

运行容器时指定了主机的文件为index.html,也指定了容器的文件路径以及文件名myindex.html,该文件在容器中不存在。使用curl访问,结果都能访问得到。

进入该容器中:

Docker动手教程4.1:容器存储1

容器中相关目录下出现了两个文件,其中myindex.html和主机上的index.html文件内容一样。

通过上面实验,可以知道:如果我们不需要覆盖容器中的文件,只需要增加新的文件,可以使用文件挂载。

问题:前面挂载的时候都是主机目录对容器目录,主机文件对容器文件,那么是否可以主机文件对容器目录呢?

测试如下:

运行容器,命令如下:

docker run -d -p 80:80 -v /root/test/index.html:/usr/local/apache2/htdocs httpd:2.4 
Docker动手教程4.1:容器存储1

容器运行失败,从错误信息可以看出主机的文件不满足要求。

至于主机目录对容器文件是否能否挂载等情景,大家可以自行测试。

总结

容器挂载主机目录

优点:

使用比较直观;可以用于测试,直接将源代码放在主机上,在主机上修改代码既能看到实际效果。

缺点:

由于数据需要保存在主机特定的目录或者文件中,不便于容器迁移到其他主机。

至此,容器挂载主机就讲解完了,大家按照上面的顺序依次实验以加深理解。

实验

运行容器,挂载主机目录

运行容器,挂载主机文件

常用命令

sudo docker rm -f $(sudo docker ps -a | awk 'NR == 1 {next} {print $1}')

sudo docker rmi -f $(sudo docker images | awk 'NR == 1 {next} {print $3}')

docker rmi httpd


分享到:


相關文章: