前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker实践(三):数据持久化及共享

Docker实践(三):数据持久化及共享

作者头像
loong576
修改2019-10-23 10:45:43
8150
修改2019-10-23 10:45:43
举报
文章被收录于专栏:运维ABC运维ABC

环境说明:

主机名

操作系统版本

IP地址

docker版本

说明

ubuntu1604

Ubuntu 16.04.5

172.27.9.31

18.09.2

docker主机

centos7

centos7.3

172.27.9.181

/

NFS服务器

ubuntu安装详见:Ubuntu16.04.5以lvm方式安装全记录

docker安装详见:Ubuntu16.04安装Docker

 在Linux上运行的Docker有三种不同的方式将数据从 Docker Host挂载到 Docker 容器,并实现数据的读取和存储:volumes、bind mounts、tmpfs。  

三者的区别在于数据存储在docker主机的位置不同。

  • Volumes(又称docker managed volume)储在主机文件系统的中,由docker管理(在Linux上默认位置为/var/lib/docker/volumes/),只有Docker进程能修改该位置,Volumes是在Docker中保存数据的最佳方式。
  • Bind mounts可以存储在主机系统的任何位置,可能是重要的系统文件或目录,Docker主机或Docker容器上的非Docker进程可以随时修改它们。
  • tmpfs挂载仅存储在主机系统的内存中,不写入主机系统的文件系统。 

一、Volumes

简介

volumes(也被称为Docker-managed volumes)是保存Docker容器生成和使用的数据的首选机制。相较于bind mounts依赖于主机的目录结构,volumes完全由Docker管理。与bind mounts相比,volumes有几个优势:

  • 与bind mounts相比,volumes更容易备份或迁移。
  • 可以使用docker cli命令或docker api管理volumes。
  • volumes可以在Linux和Windows容器上工作。
  • 可以更安全地在多个容器之间共享volumes。
  • Volume drivers可以实现在远程主机或云主机存储数据以供加密卷的内容,或添加其他功能。
  • 新的volumes可以通过容器预先填充其内容。

此外,volumes通常比在容器的可写层中保存数据更好,因为volumes不会增加使用它的容器的大小,并且volumes的内容存在于给定容器的生命周期之外(即使容器被销毁volumes也会保存在docker host的文件系统中)

volumes在docker host的位置:

Volumes测试

1.新建Volume

root@ubuntu1604:~# docker volume create my-vol
my-vol

2.列出Volumes

root@ubuntu1604:~# docker volume ls
DRIVER              VOLUME NAME
local               my-vol

3.查看volume详情

root@ubuntu1604:~# docker volume inspect my-vol
[
    {
        "CreatedAt": "2019-03-25T15:02:16+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

volume 在host上的默认目录为:/var/lib/docker/volumes/$(VOLUME NAME)/_data

新建的volume内容为空

root@ubuntu1604:~# ll /var/lib/docker/volumes/my-vol/_data
total 8
drwxr-xr-x 2 root root 4096 Mar 25 15:02 ./
drwxr-xr-x 3 root root 4096 Mar 25 15:02 ../

4.使用volume

4.1新建container

新建container myweb01并使用volume my-vol

root@ubuntu1604:~# docker run -d -p 80:80 -v my-vol:/usr/local/apache2/htdocs --name myweb01 httpd

容器myweb01的80端口被映射为主机的80端口,my-vol被挂载到apache server存放静态文件的目录/usr/local/apache2/htdocs  

4.2访问myweb01
root@ubuntu1604:~# curl 172.27.9.31:80
<html><body><h1>It works!</h1></body></html>
4.3再次查看volume内容
root@ubuntu1604:~# ll /var/lib/docker/volumes/my-vol/_data                                        
total 12
drwxr-sr-x 2 root www-data 4096 Mar 25 15:30 ./
drwxr-xr-x 3 root root     4096 Mar 25 15:02 ../
-rw-r--r-- 1 root src        45 Jun 12  2007 index.html
root@ubuntu1604:~# more /var/lib/docker/volumes/my-vol/_data/index.html 
<html><body><h1>It works!</h1></body></html>

发现容器myweb01的内容index.html被复制到volume中,这也印证了前面所讲的volumes的特点之一:“新的volumes可以通过容器预先填充其内容” 

4.4更新数据并访问
root@ubuntu1604:~# echo "update volumes:loong576" >/var/lib/docker/volumes/my-vol/_data/index.html 
root@ubuntu1604:~# curl 172.27.9.31:80                                                             
update volumes:loong576

更新volume中的index.html,发现容器myweb01的访问内容也一并更新。  

4.5销毁volume
root@ubuntu1604:~# docker rm -f -v myweb01
myweb01
root@ubuntu1604:~# more /var/lib/docker/volumes/my-vol/_data/index.html
update volumes:loong576
root@ubuntu1604:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@ubuntu1604:~# docker volume ls
DRIVER              VOLUME NAME
local               my-vol
root@ubuntu1604:~# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
my-vol

Total reclaimed space: 24B
root@ubuntu1604:~# docker volume ls   
DRIVER              VOLUME NAME
root@ubuntu1604:~# more /var/lib/docker/volumes/my-vol/_data/index.html
more: stat of /var/lib/docker/volumes/my-vol/_data/index.html failed: No such file or directory

当销毁容器时,volume没有被同时消除,留下孤儿volume,通过docker volume prune即可删除   

二、Bind mounts  

简介

 Docker早期就有了Bind mounts。与volumes相比,Bind mounts的功能有限。使用Bind mounts时,主机上的文件或目录将装载到容器中。文件或目录由其在主机上的完整路径或相对路径引用。相反,使用卷时,会在主机上Docker的存储目录中创建一个新目录,Docker管理该目录的内容。

 对于Bind mounts,文件或目录不需要已经存在于Docker主机上。如果它还不存在,则按需创建。Bind mounts的性能非常好,但它们依赖于主机的文件系统,该文件系统具有特定的可用目录结构。如果您正在开发新的Docker应用程序,请考虑改用volumes。另外不能使用docker cli命令直接管理绑定装载。

Bind mounts在docker host的位置:

Bind mounts测试

本文使用NFS作为Bind mounts的挂载点

NFS搭建配置详见:Centos7下NFS服务器搭建及客户端连接配置

1.挂载nfs并新建index.html

root@ubuntu1604:~# mount -t nfs 172.27.9.181:/nfs /mywebtest 
root@ubuntu1604:~# df -h
Filesystem               Size  Used Avail Use% Mounted on
udev                     467M     0  467M   0% /dev
tmpfs                     98M  5.9M   92M   7% /run
/dev/mapper/rootvg-root  4.6G  539M  3.8G  13% /
/dev/mapper/rootvg-usr   4.6G  921M  3.5G  21% /usr
tmpfs                    488M     0  488M   0% /dev/shm
tmpfs                    5.0M     0  5.0M   0% /run/lock
tmpfs                    488M     0  488M   0% /sys/fs/cgroup
/dev/sda1                453M   59M  367M  14% /boot
/dev/mapper/rootvg-tmp   4.6G  9.6M  4.4G   1% /tmp
/dev/mapper/rootvg-opt   4.6G  9.6M  4.4G   1% /opt
/dev/mapper/rootvg-var   4.6G  470M  3.9G  11% /var
/dev/mapper/rootvg-home  4.6G  9.6M  4.4G   1% /home
cgmfs                    100K     0  100K   0% /run/cgmanager/fs
tmpfs                     98M     0   98M   0% /run/user/0
172.27.9.181:/nfs        6.0G   97M  5.9G   2% /mywebtest
root@ubuntu1604:~# cd /mywebtest/ && touch index.html && echo "bind mount webtest:loong576" > index.html
root@ubuntu1604:/mywebtest# more index.html 
bind mount webtest:loong576

/mywebtest被挂载到远程的nfs服务器172.27.9.181的/nfs目录,并在/mywebtest目录新建index.html文件

2.新建container myweb02

root@ubuntu1604:~# docker run -d -p 81:80 -v /mywebtest/:/usr/local/apache2/htdocs --name myweb02 httpd
749a107648450a627a03fadc29680a0cdaff1e68ba10421ddebb52e2f7f7baf4

新建容器myweb02,将 /mywebtest挂载到容器/usr/local/apache2/htdocs,容器的80端口映射为主机的81端口。

3.访问myweb02

root@ubuntu1604:~# curl 172.27.9.31:81
bind mount webtest:loong576

发现访问内容为刚刚新建的index.html,bind mounts的内容覆盖了了容器的index.html。

4.更新index.html

root@ubuntu1604:~# echo "update bind mount webtest:loong576 02" >/mywebtest/index.html 
root@ubuntu1604:~# curl 172.27.9.31:81                                                 
update bind mount webtest:loong576 02

更新index.html,访问myweb02,发现一并更新

5.销毁容器

root@ubuntu1604:~# docker rm -f myweb02
myweb02
root@ubuntu1604:~# docker ps -a        
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@ubuntu1604:~# more /mywebtest/index.html 
update bind mount webtest:loong576 02

容器myweb02被销毁,但是Bind mounts继续存在。

volumes与bind mounts异同:

不同点

volumes

bind mounts

Source位置

/var/lib/docker/volumes/...

可以任意指定

对已有挂载点影响

容器内数据复制到volume

覆盖掉容器的内容

是否支持单个文件

不支持,只能是目录

支持

权限控制

读写或者只读

读写或者只读

移植性

强,无需指定host目录

弱,与host path绑定

三、tmpfs mounts

简介

 volumes和bind mounts允许您在主机和容器之间共享文件,这样即使容器停止,您也可以保留数据。

 如果您在Linux上运行docker,则有第三个选项:tmpfs mounts。当使用tmpfs装载创建容器时,容器可以在容器的可写层之外创建文件。

 与volumes和bind mounts不同,tmpfs挂载是临时的,并且只持久存在于主机内存中。当容器停止时,tmpfs挂载将被删除,在那里写入的文件将不会被持久化。

tmpfs mounts在docker host的位置:

tmpfs mounts测试

1.新建container myweb03

root@ubuntu1604:~# docker run -d -p 82:80 --tmpfs /web03 --name myweb03 httpd 

新建容器myweb03,容器对目录/web03所有的读写操作都在内存中。

2.新建test.txt

root@ubuntu1604:~# docker exec -it myweb03 bash                              
root@f91161779960:/usr/local/apache2# cd /web03/ && echo tmpfs-test > test.txt
root@f91161779960:/web03# more test.txt 
tmpfs-test

在/web03中新建测试文件test.txt,重启容器后观察该文件是否存在。

3.重启myweb03

root@ubuntu1604:~# docker stop myweb03
myweb03
root@ubuntu1604:~# docker start myweb03
myweb03
root@ubuntu1604:~# docker exec -it myweb03 bash
root@f91161779960:/usr/local/apache2# cd /web03/
root@f91161779960:/web03# ls -l
total 0

重启容器,发现测试文件test.txt消失。

四、容器间的数据共享

bind mounts方式

 该方式为依赖于主机的共享,多个容器通过 Volume 绑定到主机上的相同位置

1.新建index.html

root@ubuntu1604:~# echo "container datas share : bind mounts" > /mywebtest/index.html

2.新建container web01 web02 web03

root@ubuntu1604:~# docker run -d -p 7701:80 -v /mywebtest/:/usr/local/apache2/htdocs --name web01 httpd       
cfa46a13458aa650c2d3243460f38ef0a53d4f8d4643633b34edb1c257fa56f6
root@ubuntu1604:~# docker run -d -p 7702:80 -v /mywebtest/:/usr/local/apache2/htdocs --name web02 httpd 
4655998a69590653af9e41eaa92e48a3798666e79a70f55f9ca33d5c1e60ea05
root@ubuntu1604:~# docker run -d -p 7703:80 -v /mywebtest/:/usr/local/apache2/htdocs --name web03 httpd 
69e917fbbb20f8a5b886b14ffa05ee93d28461e551eaf4caf9abc0610f60943b

新建容器web01/web02/web03,将主机的/mywebtst分别挂载到容器的usr/local/apache2/htdocs目录。

3.访问web

root@ubuntu1604:~# curl 172.27.9.31:7701
container datas share : bind mounts
root@ubuntu1604:~# curl 172.27.9.31:7702
container datas share : bind mounts
root@ubuntu1604:~# curl 172.27.9.31:7703
container datas share : bind mounts

在/web03中新建测试文件test.txt,重启容器后观察该文件是否存在。

4.更新index.html

root@ubuntu1604:~# echo "container datas share 02 : bind mounts" > /mywebtest/index.html 
root@ubuntu1604:~# curl 172.27.9.31:7701                                                 
container datas share 02 : bind mounts
root@ubuntu1604:~# curl 172.27.9.31:7702
container datas share 02 : bind mounts
root@ubuntu1604:~# curl 172.27.9.31:7703
container datas share 02 : bind mounts

更新并再次访问web,发现所有容器的web访问页面已更新。

Volume container方式

 创建一个容器专门用于定义Volumes(可以是上文提到的volumes也可以是bind mounts),这个容器可以不运行,因为停止的容器也会保留对Volume的引用。然后其它的容器在创建或运行时通过--volumes-from从该容器复制Volume定义。 

使用该方式的注意事项:

  • 一般容器名加前缀 vc_,表示 volume container
  • 涉及的各容器对于 Volume 绑定的目录位置及命名规范都必须协同一致

1.新建container vc_data

root@ubuntu1604:~# docker create -v /mywebtest/:/usr/local/apache2/htdocs -v /apps --name vc_data  busybox

使用的busybox无实际意义,该镜像很小很适合测试

2.查看vc_data

root@ubuntu1604:~# docker inspect vc_data

/mywebtest/通过bind mounts方式挂载到容器/usr/local/apache2/htdocs目录,卷6a635ec450eeecd487df4f25615c14443aa2a4da07b8c605a031d5ab9b5bbf47通过volume方式挂载至容器/apps目录。

3.使用vc_data

root@ubuntu1604:~# docker run -d -p 7704:80 --volumes-from vc_data --name web04 httpd
25ff55566720281791f2b1956236204dbca6ad529fa460a76d80e970786df22d
root@ubuntu1604:~# docker run -d -p 7705:80 --volumes-from vc_data --name web05 httpd 
dcce95be79b1ecc888d748d684b814743583c5db1ac41f026ca4ed5525f51c67
root@ubuntu1604:~# docker run -d -p 7706:80 --volumes-from vc_data --name web06 httpd 
edd257edaf6101ee8911afeb08b70ec95673b5e1c64c774e2b00f1486b025ba8

新建容器web04/web05/web06并使用vc_data。

4.查看web04

root@ubuntu1604:~# docker inspect web04

挂载信息和vc_data一致。

5.共享验证

root@ubuntu1604:~# echo "abc123" > /var/lib/docker/volumes/6a635ec450eeecd487df4f25615c14443aa2a4da07b8c605a031d5ab9b5bbf47/_data/test.txt
root@ubuntu1604:~# curl 172.27.9.31:7704
container datas share : Volume container
root@ubuntu1604:~# curl 172.27.9.31:7705
container datas share : Volume container
root@ubuntu1604:~# curl 172.27.9.31:7706
container datas share : Volume container
root@ubuntu1604:~# docker exec -it web04 bash
root@25ff55566720:/usr/local/apache2# cd /apps/ && ls -l
total 4
-rw-r--r-- 1 root root 7 Mar 27 08:12 test.txt
root@25ff55566720:/apps# more test.txt 
abc123

分别在共享目录更新新建文件,各容器也能正常访问读取共享数据。

Data-packed volume container 方式

 这种模式扩展至Volume container模式。Data-packed volume container不仅定义Volumes,而且将从本容器的映像中的一些数据(如静态文件、配置数据、代码等)复制到这个定义的Volumes中,从而可与其它容器共享。

1.构建镜像

配置查看

root@ubuntu1604:~# pwd
/root
root@ubuntu1604:~# ls
Dockerfile  htdocs
root@ubuntu1604:~# more htdocs/index.html 
container datas share : Data-packed volume
root@ubuntu1604:~# more Dockerfile 
FROM busybox
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs

构建镜像

root@ubuntu1604:~# docker build -t image_datapacked .
Sending build context to Docker daemon  18.43kB
Step 1/3 : FROM busybox
 ---> d8233ab899d4
Step 2/3 : ADD htdocs /usr/local/apache2/htdocs
 ---> d9266ad06c41
Step 3/3 : VOLUME /usr/local/apache2/htdocs
 ---> Running in c7d1cab717d4
Removing intermediate container c7d1cab717d4
 ---> f8f9f9c15171
Successfully built f8f9f9c15171
Successfully tagged image_datapacked:latest

通过Dockerfile方式构建镜像,镜像名为image_datapacked

2.创建data-packed volume container

root@ubuntu1604:~# docker run -it  --name vc_datapacked image_datapacked
/ # cd /usr/local/apache2/htdocs/
/usr/local/apache2/htdocs # ls
index.html
/usr/local/apache2/htdocs # more index.html 
container datas share : Data-packed volume

运行data-packed volume container:vc_datapacked,可以看到之前写进镜像层的index.html:container datas share : Data-packed volume

查看vc_datapacked详情

root@ubuntu1604:~# docker inspect vc_datapacked  

因为在 Dockerfile中已经使用了VOLUME指令,这里就不需要指定volume的 mount point了。

volume为/var/lib/docker/volumes/3c37bc016de3018cb59292cdfca581893a77d19ba8b8f5538b04aab71b3603a1,容器挂载点为/usr/local/apache2/htdocs

3.使用vc_datapacked

root@ubuntu1604:~# docker run -d -p 7707:80 --volumes-from vc_datapacked --name web_datapacked httpd

新建容器web_datapacked并使用vc_datapacked。

4.查看web_datapacked

root@ubuntu1604:~# docker inspect web_datapacked

volume为/var/lib/docker/volumes/3c37bc016de3018cb59292cdfca581893a77d19ba8b8f5538b04aab71b3603a1,容器挂载点为/usr/local/apache2/htdocs。挂载信息和vc_datapacked一致。

5.共享验证

root@ubuntu1604:~# curl 172.27.9.31:7707
container datas share : Data-packed volume

访问容器web_datapacked的web服务,返回结果与写入镜像image_datapacked的index.html一直,实现了静态文件index.html

6.总结

  • 1.相较于volume container,data-packed volume container方式直接把共享数据写进镜像层,通过上传至私有仓库,其它docker host都能使用该镜像实现容器的数据共享;
  • 2.data-packed volume container只适用于静态数据共享;
  • 3.若要修改data-packed volume container中的共享数据,只能重建image,不能动态修改。

本文参考:

https://docs.docker.com/storage/

http://www.atjiang.com/persistent-storage-and-shared-state-with-volumes-in-docker/

https://blog.51cto.com/cloudman/1948779

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Volumes
    • 简介
      • Volumes测试
        • 1.新建Volume
        • 2.列出Volumes
        • 3.查看volume详情
        • 4.使用volume
    • 二、Bind mounts  
      • 简介
        • Bind mounts测试
          • 1.挂载nfs并新建index.html
          • 2.新建container myweb02
          • 3.访问myweb02
          • 4.更新index.html
          • 5.销毁容器
      • 三、tmpfs mounts
        • 简介
          • tmpfs mounts测试
            • 1.新建container myweb03
            • 2.新建test.txt
            • 3.重启myweb03
        • 四、容器间的数据共享
          • bind mounts方式
            • 1.新建index.html
            • 2.新建container web01 web02 web03
            • 3.访问web
            • 4.更新index.html
          • Volume container方式
            • 1.新建container vc_data
            • 2.查看vc_data
            • 3.使用vc_data
            • 4.查看web04
            • 5.共享验证
          • Data-packed volume container 方式
            • 1.构建镜像
            • 2.创建data-packed volume container
            • 3.使用vc_datapacked
            • 4.查看web_datapacked
            • 5.共享验证
            • 6.总结
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档