docker 数据管理
容器数据保存的过程
如果正在运行中的容器修如果生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录,此即“写时复制(COW) copy on write”机制
docker 数据类型
Docker 的镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中。
如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录,目前 Docker 的数据类型分为两种,一是数据卷,二是数据容器,数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上
root@z2:~# docker inspect 588c6f0d5394
“GraphDriver”: {
“Data”: {
“LowerDir”: “/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf-init/diff:/var/lib/docker/overlay2/9e36ed5730a43d3c1ff4194c79f0ddf549576947686bb751aff2d72b984e29ea/diff”,
“MergedDir”: “/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf/merged”,
“UpperDir”: “/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf/diff”,
“WorkDir”: “/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf/work”
},
“Name”: “overlay2”
},
LowerDir:image 镜像层(镜像本身,只读)
UpperDir:容器的上层(读写)
MergedDir:容器的文件系统,使用 Union FS(联合文件系统)将 lowerdir 和
upperdir 合并给容器使用。
WorkDir:容器在 宿主机的工作目录
在容器生成数据:
root@z2:~# docker exec -it 588c6f0d5394 /bin/bash
[root@588c6f0d5394 /]# mkdir /data
[root@588c6f0d5394 /]# echo "1234561" > /data/a.txt
root@z2:/var/lib/docker/overlay2# find ./ -name 'a.txt'
./8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf/diff/data/a.txt
root@z2:/var/lib/docker/overlay2# cd 8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf
root@z2:/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf# ls
diff link lower work
root@z2:/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf# tree
.
├── diff
│ └── data
│ └── a.txt
├── link
├── lower
└── work
└── work
数据在宿主机哪里?
root@z2:/var/lib/docker/overlay2/8812ffaa8ca7a8276671543d6264cbd59894e2a23065b0d6578546250c3025cf/diff/data# cat a.txt
1234561
什么是数据卷(data volume):
数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中使用。
docker run --help
-v, --volume list Bind mount a volume
--volume-driver string Optional volume driver for the container
--volumes-from list Mount volumes from the specified container(s)
1.主机目录映射到容器内部
eg:
1.1 创建 APP 目录并生成 web 页面
此 app 以数据卷的方式,提供给容器使用,比如容器可以直接宿主机本地的 web app,而需要将代码提前添加到容器中,此方式适用于小型 web 站点。
mkdir /data/testapp -p
echo "testapp page" > /data/testapp/index.html
cat /data/testapp/index.html
testapp page
1.2 启动容器并验证数据
注意: 使用-v 参数,将宿主机目录映射到容器内部,web2 的 ro 标示在容器内对该目录只读,默认是可读写的:
docker run -d --name web1 -v /data/testapp/:/apps/nginx/html/tt -p 81:80 ubuntu-nginx:1.16.1
docker run -d --name web2 -v /data/testapp/:/apps/nginx/html/tt:ro -p 82:80 ubuntu-nginx:1.16.1
root@z2:/data# curl 127.0.0.1:81/tt/
testapp page
注意:目录映射(效果可以理解为等于), 如果原来容器中没有这个目录,会自动新建。如果已经存在,则会遮盖容器中目录原有的内容。
1.3 进入到容器内测试写入数据
- 在容器内修改挂载的数据
root@z2:/data# docker exec -it web1 bash
root@ee464ee26361:/# echo 1 >> /apps/nginx/html/tt/index.html
发现是可以修改的,,同时宿主机内的数据也被修改了。 挂载这一目录的另一个容器更新了内容
root@z2:~# curl 127.0.0.1:82/tt/
testapp page
1
root@z2:~# curl 127.0.0.1:82/tt/
testapp page
1
但是web2不行。 因为加了 参数ro,默认是可以读写的
root@1125b385cfec:/# echo 1 >> /apps/nginx/html/tt/index.html
bash: /apps/nginx/html/tt/index.html: Read-only file system
- 在宿主机修改挂载的数据
root@z2:~# echo 2 >> /data/testapp/index.html
root@z2:~# curl 127.0.0.1:81/tt/
testapp page
1
2
root@z2:~# curl 127.0.0.1:82/tt/
testapp page
1
2
发现也是立即在容器内生效
1.4 删除容器时
创建容器的时候指定参数-v,可以删除/var/lib/docker/containers/的容器数据目录,但是不会删除数据卷的内容,如下:
root@z2:~# docker rm -fv `docker ps -a -q`
1125b385cfec
ee464ee26361
数据卷的内容仍然存在
root@z2:~# cat /data/testapp/index.html
testapp page
1
2
2.文件挂载
文件挂载用于很少更改文件内容的场景,比如 nginx 的配置文件、tomcat 的配置文件等。
2.1创建容器并挂载配置文件
root@z2:/data/testapp# ll
total 36
drwxr-xr-x 2 root root 4096 Jul 30 16:56 ./
drwxr-xr-x 5 root root 4096 Jul 30 16:53 ../
-rwxr-x--- 1 root root 23998 Jul 30 16:28 catalina.sh*
-rw-r--r-- 1 root root 13 Jul 30 16:53 index.html
root@z2:/data/testapp#
#自定义 JAVA 选项参数:
JAVA_OPTS="-server -Xms1g -Xmx1g -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"
#创建容器:
docker run -it -d -p 8080:8080 -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro linux37-tomcat:app1
2.2 验证参数生效
2.3 进入容器测试文件读写
加 ! 也不行
2.4 如何一次挂载多个目录
root@z2:/# mkdir /data/mage
root@z2:/# echo mage6666 > /data/mage/index.html
启动容器,多加-v 参数就行
docker run -it -d -p 8080:8080 -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/mage/:/data/tomcat/webapps/mage:ro linux37-tomcat:app1
验证
root@z2:/# curl 127.0.0.1:8080/mage/
mage6666
root@z2:/# ps -ef |grep java
2020 6010 5945 9 10:41 ? 00:00:02 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/apps/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xms1g -Xmx1g -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 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/apps/tomcat -Dcatalina.home=/apps/tomcat -Djava.io.tmpdir=/apps/tomcat/temp org.apache.catalina.startup.Bootstrap start
root 6062 4937 0 10:42 pts/0 00:00:00 grep --color=auto java
root@z2:/# /
3.数据卷总结
特点
- 数据卷是宿主机的目录或者文件,并且可以在多个容器之间共同使用。
- 在宿主机对数据卷更改数据后会在所有容器里面会立即更新。
- 数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
- 在容器里面的写入数据不会影响到镜像本身。
使用场景
- 日志输出
- 静态 web 页面
- 应用配置文件
- 多容器间目录或文件共享
数据卷容器
数据卷容器功能是可以让数据在多个 docker 容器之间共享,即可以让 B 容器访问 A 容器的内容,而容器 C 也可以访问 A 容器的内容,即先要创建一个后台运行的容器作为 Server,用于卷提供,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为 client 端:
1.先启动一个容器,并挂载宿主机的数据目录:
将宿主机的 catalina.sh 启动脚本和 magedu 的 web 页面,分别挂载到卷容器 server端,然后通过 server 端共享给 client 端使用。
docker run -d --name volume-server -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/mage:/data/tomcat/webapps/maged linux37-tomcat:app1
2.启动端容器 Client
# docker run -d --name web1 -p 8801:8080 --volumes-from volume-server linux37-tomcat:app1
[root@113f7e44db99 /]# echo 1 >> /data/tomcat/webapps/maged/index.html
[root@113f7e44db99 /]# echo 1 >> /apps/tomcat/bin/catalina.sh
bash: /apps/tomcat/bin/catalina.sh: Read-only file system
说明了client 端容器所挂载之后的权限 ,继承至卷sever
3.当卷server发生故障时,客户端容器的对挂载目录的访问情况
当卷sever 容器停止时
root@z2:~# docker stop volume-server
volume-server
root@z2:~# curl 127.0.0.1:8801/maged/
mage6666
1
3.1.1 server容器停止时,client 仍然可以访问使用。
docker run -d --name web2 -p 8802:8080 --volumes-from volume-server linux37-tomcat:app1
root@z2:~# docker run -d --name web2 -p 8802:8080 --volumes-from volume-server linux37-tomcat:app1
16a056dc43de5df3b9c6605b28ec95e1ad18506bade5591b4e8f32405c2a1883
root@z2:~#
3.1.2 server容器停止时,client 容器仍然可以创建。
root@z2:~# curl 127.0.0.1:8802/maged/
mage6666
1
3.1.3 server容器停止时,client 容器仍然可以创建并且访问。
当卷sever 容器被删除时
root@z2:~# docker rm -fv volume-server
volume-server
3.2.1 server容器被删除时,已经运行的client 容器不影响使用
root@z2:~# curl 127.0.0.1:8801/maged/
mage6666
1
root@z2:~# curl 127.0.0.1:8802/maged/
mage6666
3.2.2 server容器被删除时但是无法创建的新的容器
root@z2:~# docker run -d --name web3 -p 8803:8080 --volumes-from volume-server linux37-tomcat:app1
Unable to find image 'linux37-tomcat:app1' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/library/linux37-tomcat/manifests/app1: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Flinux37-tomcat%3Apull&service=registry.docker.io: net/http: TLS handshake timeout.
3.2.3若把删除的卷server 删除后再创建,不影响新的client 容器创建
root@z2:~#
root@z2:~# docker run -d --name volume-server -v /data/testapp/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/mage:/data/tomcat/webapps/maged linux37-tomcat:app1
a036b2719e2e5de7b6c8789dba07fd55d0b14437a21fe237ae1aa52f28956314
root@z2:~# docker run -d --name web3 -p 8803:8080 --volumes-from volume-server linux37-tomcat:app1
235ef61c52b821e0382b95f65729554eddf835c4d1a52e81d90694100923e123
3.3.4 总结
-
在当前环境下,即使把提供卷的容器 Server 删除,已经运行的容器 Client 依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器 Server 创建后即可正常创建卷容器 Client,此方式可以用于线上共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用
-
数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于 NFS 共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性。