docker inspect 容器ID
lowerdir层
在docker
镜像中这一层称为init
,构成容器文件系统的文件路径集合,通过 冒号 : 分割,越是后面的表示越底层。 由于组成LowerDir
的镜像层是不可修改的,因此他们可以被一个宿主机上所有容器共用的一层。
lowerdir
是只读的镜像层(image layer
),其中就包含bootfs/rootfs
层,bootfs(boot file system)
主要包含bootloader
和kernel
,bootloader
主要是引导加载kernel
,当boot
成功 kernel
被加载到内存中,bootfs
就被umount
了,rootfs(root file system)
包含的就是典型Linux
系统中的/dev、/proc、/bin、/etc
等标准目录。
lowerdir
是可以分很多层的,除了bootfs/rootfs
层以外,还可以通过Dockerfile
建立很多image
层,构建过程如下:
Dockerfile
中每一个指令都会生成一个新的image
层,如上图所示。
当FROM
时就已经生成了bootfs/rootfs
层,也就是kernel
和base
层。
upperdir层
upperdir
层是lowerdir
的上一层,只有这一层可读可写的,其实就是Container
层,在启动一个容器的时候会在最后的image
层的上一层自动创建,所有对容器数据的更改都会发生在这一层。
docker
将一个镜像作为lowerdir
层,并且建立一个upperdir
层,upperdir
层也称为容器读写层(联想我们在docker
容器里编辑或者新增文件)。最后将这两层挂载到一个特定的路径下,最终形成docker
容器的rootfs
。
由于联合文件系统采用了copy-on-wirte
的方式来读写文件:当对一个文件进行编辑的时候,会先从上至下逐层查找,如果找到了就copy
到upper
层,然后进行在upperdir
层对文件进行修改。
merged层
merged
是容器层和镜像层的联合视图
merged
层就是联合挂载层,也就是给用户暴露的统一视觉,将image
层和container
层结合,就如最上边的图中描述一致,同一文件,在此层会展示离它最近的层级里的文件内容,或者可以理解为,只要container
层中有此文件,便展示container
层中的文件内容,若container
层中没有,则展示image层中的。
在merge
路径下 编辑/写入一个文件,其首先会从upper
层中寻找看是否存在目标文件,如果存在,则直接修改,如果不存在,则跳入到lower
层查找,如果找到了,会把lower
层的目标文件拷本一份到upper
层,然后对拷贝到upper
层的目标文件进行编辑,如果在lower
层也查不到,则会将编辑的文件保存一份到upper
层。这样,最后用户在merge
层看到的视图就是 编辑/写入 的文件。
联合挂载系统的工作原理
如果文件在upperdir
(容器)层,直接读取文件;
如果文件不在upperdir
(容器)层,则从镜像层(lowerdir
)读取;
首次写入:如果upperdir
中不存在,overlay
和overlay2
执行copy_up
操作,把文件从lowdir
拷贝到upperdir
中,由于overlayfs
是文件级别的(即使只有很少的一点修改,也会产生copy_up
的动作),后续对同一文件的再次写入操作将对已经复制到容器层的文件副本进行修改,这也就是尝尝说的写时复制(copy-on-write
)。
删除文件或目录:当文件被删除时,在容器层(upperdir
)创建whiteout文件,镜像层(lowerdir
)的文件是不会被删除的,因为它们是只读的,但without文件会阻止它们显示,当目录被删除时,在容器层(upperdir
)一个不透明的目录,这个和上边的whiteout的原理一样,组织用户继续访问,image
层不会发生改变
copy_up
操作只发生在文件首次写入,以后都是只修改副本
overlayfs
只适用两层目录,,相比于比AUFS
,查找搜索都更快
容器层的文件删除只是一个“障眼法”,是靠whiteout
文件将其遮挡,image
层并没有删除,这也就是为什么使用docker commit
提交保存的镜像会越来越大,无论在容器层怎么删除数据,image
层都不会改变
容器整体构成图
docker容器数据卷
Docker
中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker
中称为数据卷(Data Volume
)
镜像产生问题
我们将应用和环境打包成一个镜像,那么数据呢,如何进行数据的持久化?
问题:容器的数据持久化和数据同步共享问题
数据卷是什么
卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性:。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
如何使用数据卷
创建数据卷,只要在docker run
命令后面跟上-v
参数即可创建一个数据卷,当然也可以跟多个-v参数来创建多个数据卷,当创建好带有数据卷的容器后,就可以在其他容器中通过--volumes-froms
参数来挂载该数据卷了,而不管该容器是否运行。也可以在Dockerfile中通过VOLUME指令来增加一个或者多个数据卷
数据卷的备份:不能使用docker export、save、cp
等命令来备份数据卷的内容,因为数据卷是存在于镜像之外的。备份方法: 创建一个新容器,挂载数据卷容器,同时挂载一个本地目录,然后把远程数据卷容器的数据卷通过备份命令备份到映射的本地目录里面。如下:
docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
Docker Volume数据卷可以实现
绕过“拷贝写”系统,以达到本地磁盘IO的性能,(比如运行一个容器,在容器中对数据卷修改内容,会直接改变宿主机上的数据卷中的内容,所以是本地磁盘IO的性能,而不是先在容器中写一份,最后还要将容器中的修改的内容拷贝出来进行同步。)
绕过“拷贝写”系统,有些文件不需要在docker commit打包进镜像文件。
数据卷可以在容器间共享和重用数据、在宿主和容器间共享数据
数据卷数据改变是直接修改的
数据卷是持续性的,直到没有容器使用它们。即便是初始的数据卷容器或中间层的数据卷容器删除了,只要还有其他的容器使用数据卷,那么里面的数据都不会丢失。
数据卷可在容器之间共享或重用数据
卷中的更改可以直接生效
数据卷中的更改不会包含在镜像的更新中
数据卷的生命周期一直持续到没有容器使用它为止
docker环境安装mysql
通过docker容器的数据卷,解决mysql数据持久化问题
拉取mysql 5.7
镜像
docker pull mysql:5.7
创建myslq需要挂载的配置文件和目录
mkdir -p /data/mysql/conf && mkdir -p /data/mysql/data && mkdir -p /data/mysql/log
#进入conf目录创建my.cnf文件
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
运行mysql ,这里需要注意启动myslq是需要配置密码的
docker run --name mysql01 -p 3306:3306 -v /data/mysql/conf/my.cnf:/etc/mysql/my.cnf -v /data/mysql/data:/var/lib/mysql -v /data/mysql/log:/var/log/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
#启动我们得
-d 后台运行
-p 端口映射
-v 卷挂载【宿主机文件/目录:容器里对应的文件/目录】
# 这里需要注意 宿主机上的文件/目录是要提前存在的
-e 环境配置
-- name 容器名字
#数据卷权限:
#挂载的数据默认为可读写权限。
#但也可以根据自己的需求,将容器里挂载共享的数据设置为只读,这样数据修改就只能在宿主机上操作
启动成功远程测试连接
测试连接正常,查看宿主机上挂载的Mysql数据
测试创建的test数据库以及被持久化
停止并且删除mysql容器
再次查看宿主机中mysql持久化的数据
数据依然存在
具名和匿名挂载
匿名挂载就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。
运行并匿名挂载nginx
容器
docker run -d -P --name nginx01 -v /etc/nginx nginx
查看所有的数据卷volume
的情况, VOLUME NAME
这里的值是真实存在的目录
具名挂载,就是指定文件夹名称,区别于指定路径挂载,这里的指定文件夹名称是在Docker指定的默认数据卷路径下的。通过docker volume ls
命令可以查看当前数据卷的目录情况。
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
4ceaff19e5275dcd3014a8e7a8af618f7f7ce0da18d605c7c41a8653e78bf912
# 挂载的时候,指定一个名称
root@iZwz99sm8v95sckz8bd2c4Z ~]# docker volume ls
DRIVER VOLUME NAME
local 0cd45ab893fc13971219ac5127f9c0b02491635d76d94183b0261953bdb52d26
local 668a94251e562612880a2fdb03944d67d1acdbbdae6ef7c94bee8685644f2956
local e605f3dc4bf11ab693972592b55fb6911e5bf2083425fd58869c5f574998a09a
local juming-nginx
查看指定的数据卷信息的命令:docker volume inspect数据卷名称
docker volume inspect
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker volume inspect juming-nginx
"CreatedAt": "2020-12-29T22:40:25+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
可以看到主机数据卷挂载在/var/lib/docker/volumes/juming-nginx/_data上
Docker所有的数据卷默认在/var/lib/docker/volumes/ 目录下
[root@iZwz99sm8v95sckz8bd2c4Z volumes]# ls
0cd45ab893fc13971219ac5127f9c0b02491635d76d94183b0261953bdb52d26 backingFsBlockDev juming-nginx
668a94251e562612880a2fdb03944d67d1acdbbdae6ef7c94bee8685644f2956 e605f3dc4bf11ab693972592b55fb6911e5bf2083425fd58869c5f574998a09a metadata.db
匿名挂载,具名挂载,指定路径挂载的命令区别如下:
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
指定数据卷映射的相关参数:
ro —— readonly 只读。设置了只读则只能操作宿主机的路径,不能操作容器中的对应路径。
rw ----- readwrite 可读可写
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
容器数据卷
容器数据卷是指建立数据卷,来同步容器之间的数据,实现容器间的数据同步【简单来说就是,容器挂载同一个目录,到达数据持久化共享据】
volumes-from容器间传递共享
容器数据卷
docker run -it --name dc02 --volunes-from dc01 leyton/centos
相关Docker文章推荐
Docker文件系统 & 数据卷
Docker 安装及基本命令
Docker 部署nginx/tomcat/ES+kibana
Docker网络
Docker C/S架构
Dockerfile自定义镜像
Image的本地存储结构【https://segmentfault.com/a/1190000017579626】
深入理解 Docker 容器镜像分层的原理【https://iswbm.com/371.html】
docker文件系统分层存储原理【https://www.cnblogs.com/v-fan/p/14453223.html】
挂载Linux系统外的文件【http://c.biancheng.net/view/885.html】