Docker 6:Docker Volume 存储卷实验

六:Docker Volume

6.1:Docker Volume 基础了解

如果正在运行中的容器生成了新的数据,或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录,此即 “写时复制(COW)copy on write” 机制。

Docker 的镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中,如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录。

6.1.1:Docker 数据写入可写层

如果 Dokcer 没有挂载 Volume 存储卷,则 Docker 容器生成的数据都存放在容器的可写层,这个可写层随容器的删除而删除。

容器的 Layers

查看容器的目录挂载:

root@ubuntu:~# docker inspect 6960834428ff

Docker 6:Docker Volume 存储卷实验_第1张图片

  • LowerDir:image 镜像层(镜像本身,只读);
  • MergedDir:容器的文件系统,使用Union FS(联合文件系统)将lowerdir和upperdir合并给容器使用;
  • UpperDir:容器的上层(读写层);
  • WorkDir:容器在宿主机的工作目录;

容器数据的存储位置

在容器中生成的数据存放在宿主机的什么地方?

在容器中生成一个 testfile 文件:

root@ubuntu:~# docker exec -it 6960834428ff bash
root@6960834428ff:/# dd if=/dev/zero of=testfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.177367 s, 591 MB/s

root@6960834428ff:/# md5sum testfile 
2f282b84e7e608d5852449ed940bfc51  testfile

宿主机查找验证:

root@ubuntu:~# find / -name testfile
/var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/merged/testfile
/var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/diff/testfile

root@ubuntu:~# md5sum /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/merged/testfile
2f282b84e7e608d5852449ed940bfc51  /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/merged/testfile

root@ubuntu:~# md5sum /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/diff/testfile
2f282b84e7e608d5852449ed940bfc51  /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/diff/testfile

可写层数据的不持久性

当容器被删除后,数据也将被删除:

root@ubuntu:~# docker rm -fv `docker ps -q`
6960834428ff

root@ubuntu:~# md5sum /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/diff/testfile
md5sum: /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/diff/testfile: No such file or directory

root@ubuntu:~# md5sum /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/merged/testfile
md5sum: /var/lib/docker/overlay2/ffa61dc6259aae6c3ac677f13f2c0201c6cfe1cb531a06065d36afc07738859e/merged/testfile: No such file or directory

6.1.2:Docker 数据写入 Volume 存储卷

如果要想让 Docker 容器的数据持久化,可以将 Docker 容器数据写入到 Volume,这就相当于将容器的数据写入到宿主机,从而在容器被删除后,容器数据依然存在。

目前 Docker Volume 的挂载方式分为两种:

  • 一是数据卷(data volume),数据卷类似于挂载在容器上的一块磁盘;
  • 二是数据卷容器(Data volume container),数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据。

数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中使用。
实际生产环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性。

6.2:Data Volume 数据卷

docker run --volume / -v :Bind mount a volume.

数据卷使用场景:

  1. 日志输出
  2. 静态web页面
  3. 应用配置文件
  4. 多容器间目录或文件共享

6.2.1:挂载 webapp 到容器

将应用程序以 Volume 的方式挂载到容器,而不是直接打入镜像容器(适用于小型站点);

  • 在宿主机上创建一个 app 目录,并放入测试页面;
  • 启动两个 Tomcat 容器,将宿主机的 app 目录挂载到两个容器;
  • 访问两个容器,查看是否可以访问到相同的 app 内容;

准备测试 webapp

使用 Tomcat 官方的 sample.war 作为测试 webapp:

root@ubuntu:~# mkdir /data/sampleapp -pv
mkdir: created directory '/data'
mkdir: created directory '/data/sampleapp'

root@ubuntu:~# cp sample.war /data/sampleapp/
root@ubuntu:~# cd /data/sampleapp/
root@ubuntu:/data/sampleapp# jar xf sample.war

启动 Tomcat 容器

拉取镜像:

root@ubuntu:~# docker pull tomcat

先启动一个容器并进入,查看 Tomcat 容器的 webapp 根目录:

root@ubuntu:~# docker run -it tomcat bash
root@377e6d44989f:/usr/local/tomcat# grep "appBase" conf/server.xml         
      

启动两个容器,分别映射宿主机的 8080 和 8081 端口,挂载 webapp 所在目录,并设为只读:

root@ubuntu:~# docker run -itd -p 8080:8080 --name tomcat8080 -v /data/sampleapp/:/usr/local/tomcat/webapps/sampleapp:ro tomcat           

root@ubuntu:~# docker run -itd -p 8081:8080 --name tomcat8081 -v /data/sampleapp/:/usr/local/tomcat/webapps/sampleapp:ro tomcat  

访问测试

http://192.168.1.111:8080/sampleapp/

Docker 6:Docker Volume 存储卷实验_第2张图片

http://192.168.1.111:8081/sampleapp/

Docker 6:Docker Volume 存储卷实验_第3张图片

宿主机修改主页内容

在宿主机将 sampleapp 的主页内容进行修改:

root@ubuntu:~# echo "sampleapp" > /data/sampleapp/index.html 

http://192.168.1.111:8080/sampleapp/

Docker 6:Docker Volume 存储卷实验_第4张图片

http://192.168.1.111:8081/sampleapp/

Docker 6:Docker Volume 存储卷实验_第5张图片

删除容器

删除容器后,宿[p0-主机的数据不受影响:

root@ubuntu:~# docker rm -fv `docker ps -aq`
42752ca08095
58273680f803

root@ubuntu:~# ll /data/sampleapp/
total 36
drwxr-xr-x 5 root root 4096 Jan 25 11:46 ./
drwxr-xr-x 3 root root 4096 Jan 25 11:45 ../
-rw-r--r-- 1 root root  376 Jan 25 11:46 hello.jsp
drwxr-xr-x 2 root root 4096 Jan 25 11:46 images/
-rw-r--r-- 1 root root   10 Jan 25 12:02 index.html
drwxr-xr-x 2 root root 4096 Jan 25 11:46 META-INF/
-rw-r--r-- 1 root root 4606 Jan 25 11:46 sample.war
drwxr-xr-x 4 root root 4096 Jan 25 11:46 WEB-INF/

root@ubuntu:~# cat /data/sampleapp/index.html 
sampleapp

6.2.2:挂载文件到容器

挂载文件到容器用于很少修改文件内容的场景,比如挂载配置文件(Nginx、Tomcat 等);

准备 catalina.sh 启动脚本

启动一个 tomcat 容器,得到 catalina.sh:

root@ubuntu:~# docker run -itd tomcat
d6847848c0a979a261c4d082cb6d3a92c47fe103ec65232ab6b8c45d6b16900f

root@ubuntu:~# find / -name "catalina.sh"
/var/lib/docker/overlay2/8eb7b75d01f746bcc3da255c4dd09fa4a9e3f1cbbb083ec88b8aa4c7e3449346/diff/apps/apache-tomcat-8.5.60/bin/catalina.sh

root@ubuntu:~# mkdir /data/scripts
root@ubuntu:~# cp /var/lib/docker/overlay2/8eb7b75d01f746bcc3da255c4dd09fa4a9e3f1cbbb083ec88b8aa4c7e3449346/diff/apps/apache-tomcat-8.5.60/bin/catalina.sh /data/scripts

添加自定义 JAVA 选项参数:

JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"

启动 Tomcat 容器

将宿主机的 /data/scripts/catalina.sh 以只读方式挂载到容器的 /usr/local/tomcat/bin/catalina.sh:

root@ubuntu:~# docker run -itd -p 8080:8080 --name tomcat1 -v /data/scripts/catalina.sh:/usr/local/tomcat/bin/catalina.sh:ro tomcat

6.3:Data Volume Container 数据卷容器

数据卷容器最大的功能是可以让数据在多个 docker 容器之间共享,即可以让容器 B 访问容器 A 的内容,而容器 C 也可以访问容器 A 的内容,相当于先创建一个后台运行的容器作为 Server,用于卷提供,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为client 端;

可以在生产中启动一个数据卷容器,挂载宿主机的文件或目录;然后其它容器分别基于此数据卷容器挂载宿主机的文件或目录,这样可以保证容器之间的数据一致性。

6.3.1:通过数据卷容器共享文件和目录

启动一个数据卷容器

将 /data/sampleapp 挂载到数据卷容器(volume-server)的 /usr/local/tomcat/webapps/sampleapp:

root@ubuntu:~# docker run -d --name volume-server -v /data/sampleapp:/usr/local/tomcat/webapps/sampleapp tomcat

启动两个容器

启动 tomcat8080 和 tomcat8081 两个容器,都从数据卷容器(volume-server)获取数据卷的挂载:

root@ubuntu:~# docker run -d  --name tomcat8080 -p 8080:8080 --volumes-from volume-server tomcat
root@ubuntu:~# docker run -d  --name tomcat8081 -p 8081:8080 --volumes-from volume-server tomcat  

访问测试

http://192.168.1.111:8080/sampleapp/

在这里插入图片描述

http://192.168.1.111:8081/sampleapp/

在这里插入图片描述

6.3.2:数据卷容器测试

停止数据卷容器后,仍可基于它启动容器

停止数据卷容器:

root@ubuntu:~# docker stop volume-server
volume-server

基于数据卷容器启动新的容器:

root@ubuntu:~# docker run -d --name tomcat8082 -p 8082:8080 --volumes-from volume-server tomcat

http://192.168.1.111:8082/sampleapp/

在这里插入图片描述

删除数据卷容器后,之前创建的容器不受影响

删除数据卷容器:

root@ubuntu:~# docker rm -fv volume-server
volume-server

之前的容器访问都正常,不受影响:

http://192.168.1.111:8080/sampleapp/

在这里插入图片描述

http://192.168.1.111:8081/sampleapp/

在这里插入图片描述

http://192.168.1.111:8082/sampleapp/

在这里插入图片描述

你可能感兴趣的:(Docker,docker,docker,volume)