两个需求
持久化:
Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。
比如redis,我们虽然利用把数据存储在内存中来提高读写速度(内存的速度比硬盘快很多),但是为了防止数据丢失,redis提供了两种持久化:rdb和aof文件。
docker持久化的方式是什么?
数据共享:
容器作为一个个集装箱是相对独立的,那么容器之间如果需要读写同一个数据块,该如何处理?
容器数据卷
docker的镜像是由多个只读的文件系统叠加在一起形成的。当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。
为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。
容器数据卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
添加数据卷:使用命令
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
运行以下命令会在容器的根目录下创建containerVolume目录,同时还会在宿主机的根目录下创建centosVolume目录:
docker run -it -v /centosVolume:/containerVolume centos /bin/bash
容器与宿主机实现数据共享
此时,处于宿主机和容器的这两个目录,增删改查等操作都是同步的
1.在宿主机中的目录新建一个文件centosfile,并编辑:
此时查看容器中目录与文件:
无论是新建的文件,还是文件的内容,都已同步至容器中。
2.在容器中编辑centosfile(>是覆盖,>>是追加):
此时查看宿主机中文件:
可见在容器中的修改也会同步到宿主机。
此时使用docker inspect 查看容器:
"Mounts": [ { "Type": "bind", "Source": "/centosVolume", "Destination": "/containerVolume", "Mode": "", "RW": true, "Propagation": "rprivate" } ],
RW为true,表示此时的权限是可读可写。
控制权限的命令操作(:ro)
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
#ro表示read only
此时使用docker inspect 查看容器:
"Mounts": [ { "Type": "bind", "Source": "/centosVolume", "Destination": "/containerVolume", "Mode": "ro", "RW": false, "Propagation": "rprivate" } ],
此时mode为ro,RW为false,这是什么意思?
1.在宿主机中的目录新建一个文件ROfile,并编辑:
此时查看容器中目录与文件:
此时,在宿主机中的修改,依然可以同步至容器。
2.在容器中编辑ROfile
提示是只读的文件系统,那可以新建文件吗?
可见,在使用设置权限的方式添加数据卷后,在宿主机中的修改依然可以同步至容器,但在容器中只读不可写。
容器停止后,是否还同步宿主机的数据
停掉容器后,在宿主机的centosVolume目录下新建文件containerStop并编辑:
重启容器并进入交互,查看容器的containerVolume目录下的文件与内容:
所以,只要在创建容器时挂载了数据卷,无论容器是否运行,都会同步宿主机的数据。
添加数据卷:使用DockerFile
Dockerfile是什么?
Dockerfile是docker中镜像的描述文件,说的直白点就是描述了镜像文件到底是由什么东西一步步构成的。
比如tomcat的DockerFIle:https://github.com/docker-library/tomcat/blob/8438be7c4c8434b617903ea5a478441ae04572c1/8.5/jdk8/openjdk/Dockerfile
如何使用Dockerfile添加数据卷?
1.根目录下新建mydocker文件夹,在该文件夹中新建编辑一个dockerfile文件
# volume test FROM centos VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] CMD echo "finished,--------success1" CMD /bin/bash
# 解释 继承centos镜像 添加两个容器卷 打印success shell /bin/bash
2.根据dockerfile文件build一个新镜像
docker build -f /mydocker/dockerfile -t nick/centos .
[root@izbp13m488196e5hna361rz mydocker]# docker build -f /mydocker/dockerfile -t nick/centos . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos ---> 300e315adb2f Step 2/4 : VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] ---> Running in b826770c140a Removing intermediate container b826770c140a ---> d75d106ff106 Step 3/4 : CMD echo "finished,--------success1" ---> Running in 9dc4873e4b86 Removing intermediate container 9dc4873e4b86 ---> 5c55449c9438 Step 4/4 : CMD /bin/bash ---> Running in e627bd6e1bf1 Removing intermediate container e627bd6e1bf1 ---> bc5060004e4f Successfully built bc5060004e4f Successfully tagged nick/centos:latest
可见build的过程是严格按照dockerfile中的描述一步步执行的,所以镜像分了很多层,最后的.表示当前目录。
3.根据这个镜像run一个容器
发现,在容器的根目录下有dataVolumeContainer1和dataVolumeContainer2两个数据卷
[root@izbp13m488196e5hna361rz mydocker]# docker run -it nick/centos /bin/bash [root@c4598aeb6ea4 /]# ls bin dataVolumeContainer1 dataVolumeContainer2 dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
宿主机中对应的默认路径在哪?
在使用命令-v添加数据卷的时候,同时指定了宿主机和容器内的目录:
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
而上述步骤中dockerfile的方式,只写明了容器内的卷目录地址,那么对应的宿主机的目录地址在哪?
使用docker inspect 容器id ,查看容器信息:
"Mounts": [ { "Type": "volume", "Name": "4170885a6bba2913a4ef435783d102418407cfae17f2fa1a10fdef53efa97cc3", "Source": "/var/lib/docker/volumes/4170885a6bba2913a4ef435783d102418407cfae17f2fa1a10fdef53efa97cc3/_data", "Destination": "/dataVolumeContainer1", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "5a4ba4ccb27fc79523dedda5f9f1af6ac305380d8af6355b7afab005d3ec9a9a", "Source": "/var/lib/docker/volumes/5a4ba4ccb27fc79523dedda5f9f1af6ac305380d8af6355b7afab005d3ec9a9a/_data", "Destination": "/dataVolumeContainer2", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ],
所以,宿主机中对应的默认路径就是:/var/lib/docker/volumes