特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
bootfs:
主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权己由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs :
在bootfs之上。 包含的就是典型Linux系统中的**/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu**,Centos等等。
平时安装的虚拟机的Centos都是好几个G ,但是docker这里才要200M
- 对于一个精简的OS, rootfs可 以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自只需要提供rootfs就行了。
- 由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
- 所以虚拟机启动是分钟级的,容器是秒级的!!!
#查看镜像分层命令
docker image inspect
重点:所有的Docker镜像都起始于一个基础镜像层,当需要进行修改或者增加新的内容的时候,就会在当前镜像层之上,创建新的镜像层。
示例:
最大好处就是资源共享。
比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
特点:
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称为容器层,容器层之下都叫镜像层!如下图所示。
docker commit 提交容器副本使之称为一个新的镜像
docker commit -m=“提交的描述信息” -a="作者" 容器id 目标镜像名:[TAG]
由于默认的Tomcat镜像的webapps文件夹中没有任何内容,需要从webapps.dist中拷贝文件到webapps文件夹。
下面自行制作镜像:就是从webapps.dist中拷贝文件到webapps文件夹下,并提交该镜像作为一个新的镜像。使得该镜像默认的webapps文件夹下就有文件。具体命令如下:
#1、启动Tomcat容器
[root@hcz666 ~]# docker run -it tomcat /bin/bash
root@b5d0f2414eba:/usr/local/tomcat# cd webapps
root@b5d0f2414eba:/usr/local/tomcat/webapps# ls
root@b5d0f2414eba:/usr/local/tomcat/webapps# cd ../
#2、将webapps.dist中拷贝文件到webapps下
root@b5d0f2414eba:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@b5d0f2414eba:/usr/local/tomcat# cd webapps
root@b5d0f2414eba:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
#ctrl+P+Q
root@b5d0f2414eba:/usr/local/tomcat/webapps# [root@hcz666 ~]#
[root@hcz666 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5d0f2414eba tomcat "/bin/bash" About a minute ago Up About a minute 8080/tcp stoic_ramanujan
[root@hcz666 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5d0f2414eba tomcat "/bin/bash" 9 minutes ago Up 8 minutes 8080/tcp stoic_ramanujan
[root@hcz666 ~]# docker exec -it b5d0f2414eba /bin/bash
root@b5d0f2414eba:/usr/local/tomcat# cd webapps
root@b5d0f2414eba:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@b5d0f2414eba:/usr/local/tomcat/webapps# cd ../
#ctrl+P+Q
root@b5d0f2414eba:/usr/local/tomcat# read escape sequence
[root@hcz666 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5d0f2414eba tomcat "/bin/bash" 20 minutes ago Up 20 minutes 8080/tcp stoic_ramanujan
#3、提交镜像作为一个新的镜像
[root@hcz666 ~]# docker commit -m="add webapps" -a="hcz" b5d0f2414eba mytomcat:1.0
sha256:924ea2a2ebdfd7e1d96e5b0ef038177dff0d3ed0ebb36f9711c0b061757ca511
[root@hcz666 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 924ea2a2ebdf 15 seconds ago 673MB
tomcat latest 266d1269bb29 11 days ago 668MB
nginx latest dd34e67e3371 12 days ago 133MB
mysql 8.0 5a4e492065c7 12 days ago 514MB
mysql latest 5a4e492065c7 12 days ago 514MB
portainer/portainer latest 580c0e4e98b0 5 months ago 79.1MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos latest 300e315adb2f 8 months ago 209MB
#4、运行新的容器
[root@hcz666 ~]# docker run -it mytomcat:1.0 /bin/bash
root@eb6d0213cc42:/usr/local/tomcat# cd webapps
root@eb6d0213cc42:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@eb6d0213cc42:/usr/local/tomcat/webapps# [root@hcz666 ~]#
[root@hcz666 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eb6d0213cc42 mytomcat:1.0 "/bin/bash" 17 seconds ago Up 15 seconds 8080/tcp condescending_mirzakhani
b5d0f2414eba tomcat "/bin/bash" 23 minutes ago Up 23 minutes 8080/tcp stoic_ramanujan
先来看看Docker的理念:
将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的,容器之间希望有可能共享数据。
Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。为了能保存数据在docker中我们使用卷。|
概述:
卷就是目录或文件,卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点:
数据卷可在容器之间共享或重用数据
卷中的更改可以直接生效
数据卷中的更改不会包含在镜像的更新中
数据卷的生命周期一直持续到没有容器使用它为止
总结:
容器的持久化
容器间继承+共享数据
#添加命令
docker run -it -v /主机目录:/容器内目录 镜像名
#挂载命令
docker inspect 容器id
1、使用命令进行添加
#在第一个会话中
#使主机上的/home/demo目录和容器的/home目录进行挂载
[root@hcz666 ~]# docker run -it -v /home/demo:/home centos /bin/bash
[root@c3e071951e83 /]# cd /home
[root@c3e071951e83 home]# ls
[root@c3e071951e83 home]#
2、查看数据卷是否挂载成功
#在第二个会话中
[root@hcz666 ~]# cd /home #进入主机的/home目录下
[root@hcz666 home]# ls #发现demo文件夹已经挂载过来了
demo demo.java hcz hcz1.txt hcz666 hcz.txt hilde lighthouse test2 www zsx
[root@hcz666 home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3e071951e83 centos "/bin/bash" 2 minutes ago Up 2 minutes dazzling_blackwell
eb6d0213cc42 mytomcat:1.0 "/bin/bash" 22 hours ago Up 22 hours 8080/tcp condescending_mirzakhani
b5d0f2414eba tomcat "/bin/bash" 23 hours ago Up 23 hours 8080/tcp stoic_ramanujan
3a5b0d6c5f23 tomcat "catalina.sh run" 42 hours ago Up 22 hours 0.0.0.0:6656->8080/tcp, :::6656->8080/tcp tomcat01
#查看挂载是否成功
[root@hcz666 home]# docker inspect c3e071951e83
[
{
"Id": "c3e071951e83a6c192a36e15d1ea4a1a669c7e15247972bf330c1ea9bbb0c6e2",
"Created": "2021-08-30T23:33:28.235392277Z",
"Path": "/bin/bash",
"Args": [],
3、容器和宿主机之间数据共享
4、容器停止退出后,主机修改后的数据自动同步
1、使用命令进行添加
#创建容器命令
[root@hcz666 home]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql03 mysql:8.0
-----------------------------------------
#命令说明:
-p(端口映射) 12345:3306:将主机的3307端口映射到docker容器的3306端口。
--name(容器名字) mysq:运行服务名字
-v(数据卷) /home/mysql/conf:/etc/mysql/conf.d :将主机/home/mysql录下的conf挂载到容器的/etc/mysql/conf.d
/home/mysql/data:/var/lib/mysql :将主机/home/mysql目录下的data目录挂载到容器的/var/lib/mysql
-e(环境配置) MYSQL_ ROOT_ PASSWORD=123456: 初始化root用户的密码。
-d(后台运行) mysql:8.0:后台程序运行mysql8.0
2、查看数据卷是否挂载成功
3、连接本地Navicat进行测试
具体可以看:[Docker03:Docker常用安装实例_hcz666的博客-CSDN博客]
4、在本地连接创建一个test数据库,查看一下主机中是否有同步
5、删除容器,挂载在本地的数据卷依旧没有丢失
匿名挂载:
#匿名挂载:就只是写了容器内的路径,没有写宿主机的路径
-v 容器内路径
[root@hcz666 home]# docker run -d -P --name nginx03 -v /etc/nginx nginx
61072689ca5ad9625cf16a05b253b54e9afd3dc0a6656a7aed9289fe075d0360
#查看所有的volume的情况
[root@hcz666 home]# docker volume ls
DRIVER VOLUME NAME
local 117c36fa03f7f9604ed1614b2ac4742dc01fd52411ecf4d1ed80c53fbb934d85
local b9a3f1325dbcc6b6ef1195b4cec7b3ac5cdabad1812fa59f3cf542817d4a7274
local c71af64016a451112d65039f46e3dc6feaf735e1e7653dbfe99e4bcff4bf347c
local e7134e61b7e023a3f2bcebf970459f61f4cc5048d4448322f65377027b8cdb98
local ee6f64526d36c075c785979e0080d80dec4dc56a876419c2b030e70c5edfa107
[root@hcz666 home]#
具名挂载:
#具名挂载:就只是写了卷名和容器内的路径,同样也没有写宿主机的路径
-v 卷名 容器内路径
[root@hcz666 home]# docker run -d -P --name nginx05 -v juming-ngnix:/etc/nginx nginx
5e19716b3dc56ce655dc2bdf189f7eccc96ad332da2cee1536d2d89bb44f0219
[root@hcz666 home]# docker volume ls
DRIVER VOLUME NAME
local 0b0093b3473bc17c1349bf713fdca0810e08d11509bae2e73ac0df3cf1413197
local 117c36fa03f7f9604ed1614b2ac4742dc01fd52411ecf4d1ed80c53fbb934d85
local b9a3f1325dbcc6b6ef1195b4cec7b3ac5cdabad1812fa59f3cf542817d4a7274
local c71af64016a451112d65039f46e3dc6feaf735e1e7653dbfe99e4bcff4bf347c
local e7134e61b7e023a3f2bcebf970459f61f4cc5048d4448322f65377027b8cdb98
local ee6f64526d36c075c785979e0080d80dec4dc56a876419c2b030e70c5edfa107
local juming-ngnix
#查看这个卷名
[root@hcz666 home]# docker volume inspect juming-ngnix
[
{
"CreatedAt": "2021-08-31T09:25:40+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-ngnix/_data",
"Name": "juming-ngnix",
"Options": null,
"Scope": "local"
}
]
[root@hcz666 home]#
所有的docker容器内的卷,如果没有指定宿主机目录的情况下,默认都是在路径下:/var/lib/docker/volumes/juming-ngnix/_data"
区别:
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 #具体挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
#可以在DockerFile中使用VOLUME指令来给镜像添加一个或多个数据卷
VOLUME ["volume01","volume02"] #这里属于匿名挂载
#说明:
- 出于可移植和分享的目的,只用方式一不能够直接在DockerFile中实现
- 由于宿主机目录是依赖于特定宿主机的,并不能够保证所有的宿主机上都存在这样的特定的目录
1、创建自定义文件夹
[root@hcz666 home]# mkdir docker-test-volume
[root@hcz666 home]# ls
demo docker-test-volume hcz1.txt hcz.txt lighthouse test2 zsx
demo.java hcz hcz666 hilde mysql www
[root@hcz666 home]# cd docker-test-volume/
[root@hcz666 docker-test-volume]# pwd
/home/docker-test-volume
2、创建一个dockerfile文件,名字随意
#构建脚本
FROM centos
VOLUME ["volume01","volume02"] #这里属于匿名挂载
CMD echo "--------finished--------"
CMD /bin/bash
3、build后生成镜像
#构建自定义镜像命令
[root@hcz666 docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile -t hcz/centos:1.0 .
4、启动容器
[root@hcz666 docker-test-volume]# docker run -it 45648d270480 /bin/bash
4、查看主机对应默认的地址
[root@hcz666 _data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
23de7c512bc1 45648d270480 "/bin/bash" 9 minutes ago Up 9 minutes magical_noyce
[root@hcz666 _data]# docker inspect 23de7c512bc1
……省略……
"Mounts": [
{
"Type": "volume",
"Name": "b0227290658396c919bccf35dca0d3cb58c9c24cb552cd4fedfab617c62ea02d",
"Source": "/var/lib/docker/volumes/b0227290658396c919bccf35dca0d3cb58c9c24cb552cd4fedfab617c62ea02d/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "30f4ff1fcc1722912bfc7528dd3e7869d88033de31a236301538b21f393a3c8e",
"Source": "/var/lib/docker/volumes/30f4ff1fcc1722912bfc7528dd3e7869d88033de31a236301538b21f393a3c8e/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
……省略……
5、测试数据同步
[root@hcz666 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hcz/centos 1.0 45648d270480 43 minutes ago 209MB
[root@hcz666 ~]# docker run -it --name docker01 hcz/centos:1.0
[root@d93a04629b62 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Aug 31 02:44 dev
drwxr-xr-x 1 root root 4096 Aug 31 02:44 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 2020 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 131 root root 0 Aug 31 02:44 proc
dr-xr-x--- 2 root root 4096 Dec 4 2020 root
drwxr-xr-x 11 root root 4096 Dec 4 2020 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 31 02:05 sys
drwxrwxrwt 7 root root 4096 Dec 4 2020 tmp
drwxr-xr-x 12 root root 4096 Dec 4 2020 usr
drwxr-xr-x 20 root root 4096 Dec 4 2020 var
drwxr-xr-x 2 root root 4096 Aug 31 02:44 volume01
drwxr-xr-x 2 root root 4096 Aug 31 02:44 volume02
多个MySQL实现数据共享
#第一个数据库
[root@hcz666 home]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /etc/mysql/conf.d -v /var/lib/mysql --name mysql01 mysql:8.0
#第二个数据库
[root@hcz666 home]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /etc/mysql/conf.d -v /var/lib/mysql --name mysql02 --volumes -from mysql01 mysql:8.0
#第三个数据库
[root@hcz666 home]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /etc/mysql/conf.d -v /var/lib/mysql --name mysql03 --volumes -from mysql01 mysql:8.0
容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止;但是一旦持久化到了本地,这个时候,本地的数据是不会删除的。