一、容器的数据管理介绍
1.1 Docker容器分层
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即"写时复制(COW copy on write)"机制。
如果将正在运行中的容器修改生成了新的数据,那么新产生的数据将会被复制到读写层,进行持久化保存,这个读写层也就是容器的工作目录,也为写时复制(COW) 机制。
COW机制节约空间,但会导致性低下,虽然关闭重启容器,数据不受影响,但会随着容器的删除,其对应的可写层也会随之而删除,即数据也会丢失.如果容器需要持久保存数据,并不影响性能可以用数据卷技术实现。
Docker镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层中。
容器的数据分层目录:
LowerDir:images镜像层,即镜像本身,只读。
UpperDir:容器的上层,可读写,容器变化的数据存放在此处
MergedDir:容器的文件系统,使用Union FS(联合文件系统)将lowerdir和upperdir合并完成后给容器使用,最终呈现给用户的统一视图。
WorkDir:容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见。
范围:查看指定容器数据分层:docker inspect。
1.2 数据持久化
有状态的协议:有状态协议就是就通信双方要记住双方,并且共享一些信息。而无状态协议的通信每次都是独立的,与上一次的通信没什么关系。
"状态"可以理解为"记忆",有状态对应有记忆,无状态对应无记忆。
左侧是无状态的http请求服务,右侧为有状态
下层为不需要存储的服务,上层为需要存储的部分服务
1.3 持久保存方式
如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录
Docker的数据类型分为两种:
数据卷(Data Volume): 直接将宿主机目录挂载至容器的指定的目录 ,推荐使用此种方式,此方式较常用。
数据卷容器(Data Volume Container): 间接使用宿主机空间,数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据 ,此方式不常用。
二、数据卷
2.1 数据卷使用场景
数据库
日志输出
静态web页面
应用配置文件
多容器间目录或文件共享
2.2 数据卷的特点
数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用对数据卷更改数据在所有容器里面会立即更新。
数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新。
依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理。
匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中。
2.3 数据卷使用方法
启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种。
-
指定宿主机目录或文件: 指定宿主机的具体路径和容器路径的挂载关系。容器和真机共用空间, 把容器的文件挂载到 真机的文件夹。
-
匿名卷: 不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载。
-
命名卷: 指定数据卷的名称和容器路径的挂载关系和匿名卷在一个目录 ,只是取了一个自定义的名字。
docker run 命令的以下格式可以实现数据卷
-v, --volume=[host-src:]container-dest[:<options>]
<options>
ro 从容器内对此数据卷是只读,不写此项默认为可读可写
rw 从容器内对此数据卷可读可写,此为默认值
指定宿主机目录或文件格式:
-v <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro] #将宿主机目录挂载容器目录,两个目录
都可自动创建
**案例:**docker本地镜像
我们指定宿主机的/mnt/下挂载到容器中的/opt/下。前者是宿主机目录:容器中的目录
再开一个终端,去宿主机的/mnt/下查看。是否建立了abc123文件夹
匿名卷,只指定容器内路径
没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径
-v <容器内路径>
#示例:
docker run --name nginx -v /etc/nginx nginx
示例:至指定容器中的目录。
在容器中挂载位置创建一个文件。
容器中的目录/etc/nginx/下。创建文件TestFile
在宿主机中查看是否有我们创建的文件。
命名卷
#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume create <卷名>
#示例:
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html/ nginx
直接在本机修改主页:
这里的docker run -d -p 80:80 --name nginx01 -v /data/nginx/vol1:/usr/share/nginx/html/ nginx也可以指定绝对路径。
docker rm 的 -v 选项可以删除容器时,同时删除相关联的匿名卷
2.4 实战案例: 在宿主机创建容器所使用的目录
使用Dockerfile构建镜像,在宿主机中创建容器所使用的目录。
bash
[root@Node2 system]#:ls
Centos-7.repo Centos-8.repo Dockerfile epel-7.repo index.html nginx-1.18.0.tar.gz qh.repo
#写Dockerfile文件
[root@Node2 system]#:cat Dockerfile
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
version="1.0"
RUN rm -rf /etc/yum.repos.d
COPY epel-7.repo /etc/yum.repos.d/
ADD qh.repo /etc/yum.repos.d/
RUN yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib zlib-devel openssl openssl-devel wget
ADD nginx-1.18.0.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.18.0 && ./configure --prefix=/apps/nginx && make && make install
VOLUME [ "/apps/nginx/html" ]
COPY index.html /apps/nginx/html/
CMD [ "-g","daemon off;" ]
EXPOSE 80 443
ENTRYPOINT ["/apps/nginx/sbin/nginx"]
#主页
[root@Node2 system]#:cat index.html
7-2 7-2
构建镜像:
运行容器:查看端口并访问nginx服务。
在本地修改主页:通过find找到主页位置:修改index.html文件
我们可以指定宿主机共享的目录:使用上面我们构建的镜像。
在宿主机指定一个共享目录。/data/testdir/
写一个首页。运行centos7:v1容器。暴露端口。
docker run -d -p 80:80 -v /data/centNginx/:/apps/nginx/html/ --name web1 centos7:v1
可以发现。把主页写在了本地。直接访问宿主机IP。默认80端口。访问出来了我们指定的首页。
三、容器服务器数据卷
容器服务器数据卷是指在一个宿主机的目录,作为挂载点。将该目录下的文件挂载到多个容器中的目录下。使得多个容器能够共享目录。其实还是通过宿主机的目录下向多个容器共享目录。
一个容器中的目录与宿主机的目录共享后,第二个容器通过--volumes-from [第一个容器的名字]
运行一个容器。共享本机的/data/testdir/目录。与容器中的/usr/share/nginx/html/。
宿主机的/data/testdir/作为容器服务器数据卷。再运行一个容器,指向该目录。
修改宿主机的index.html文件:查看两个容器是否跟着改变:
修改容器91中的index.html文件。看2c容器中的主页是否同步跟着改变。
这样就通过宿主机作为容器服务器数据卷。为多个容器共享存储。使用--volumes-from指定容器服务器。
---end---