4.Docker镜像原理
Docker镜像原理
Docker 10 镜像原理
联合文件系统
联合文件系统(UnionFS)是 Docker 的核心,也是 Docker 得以极致精简的保证。
以拉取 redis 镜像为例
先拉取最新版镜像
1 | [root@sail ~]# docker pull redis |
再拉取指定版镜像
1 | [root@sail ~]# docker pull redis |
由此可见,redis 镜像一共 6 层,由于之前拉取了默认的最新版 redis 镜像,再拉取 redis:5.0 时,有 3 层是可以复用的,所以只下载了不能复用的 3 层。
这样既能提高下载速度,也能极大节省磁盘占用和资源消耗。
分层镜像
Docker 使用联合文件系统对镜像做了分层,如下图所示:
- bootfs(boot file system):启动文件系统。
- rootfs:root file system:基础文件系统。
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加到镜像的顶部。
这一层就是我们通常说的容器层,容器层之下的都叫镜像层。
我们自己也是可以制作镜像并提交的,使用 docker commit
命令。
Docker自定义镜像
提交镜像
docker commit
语法
1 | docker commit [参数] 容器 [仓库[:标签]] |
参数
a
:作者信息。一般为 作者名字<邮箱>。c
:将 Dockerfile 指令应用于创建的映像。m
:注释信息。p
:提交期间暂停容器(默认)。
将这个容器创建为一个自定义的镜像并提交到仓库中。
1 | [root@sail ~]# docker commit -a="sail<yifansailing@163.com>" -m="diy tomcat by sail" fe247e0ef80d tomcat4sail:1.0 |
可以看到,我们自定义的镜像已经在本地镜像库中了。
测试
停止原有容器。
1 | [root@sail ~]# docker stop fe247e0ef80d |
启动自定义镜像。
1 | [root@sail ~]# docker run -d -p 8080:8080 --name="tomcat4sail" 187a99503046 |
由于自定义的镜像还没有提交到远程库,所以这里只能使用镜像 ID 启动。
如果使用镜像名启动,会从远程库中进行搜索,由于我们还没有提交,会因为搜索不到报错。
访问测试
这里我们并没有改变容器中 webapps 下的内容,但依然可以直接访问,说明我们自定义的镜像是生效了的。
Docker数据卷 挂载
由来
Docker 是将应用和环境打包成一个镜像。
这样,数据就不应该保存在容器中,否则容器删除,数据就会丢失,有着非常大的风险。
为此,容器和主机之间需要有一个数据共享技术,使得在 Docker 容器中产生的数据能够同步到本地。
这就是数据卷技术。其本质上是一个目录挂载,将容器内的目录挂载到主机上。
使用
命令方式
语法
1 | docker run -v 主机目录:容器目录 |
查看主机 /home 目录。
1 | [root@sail ~]# ls /homeadmin f2 f3 sail test.java |
以交互模式启动 centos 镜像。
1 | [root@sail ~]# docker run -it -v /home/ceshi:/home centos /bin/bash |
新开一个窗口查看容器详情。
Mounts 下的 Source 即为设置的主机目录、Destination 即为设置的容器目录,他们已经绑定在了一起。
在主机中查看 /home。
1 | [root@sail /]# cd /home |
主机上的 /home
下已经有了 ceshi
目录。说明容器一经启动,就会在主机生成对应的挂载目录。
在容器中的 /home 下新建一个文件。
1 | [root@ec95646b1a4c /]# cd /home |
查看主机的 ceshi 目录。
1 | [root@sail home]# cd ceshi |
此时主机中的 ceshi
目录下也有了这个文件。
关闭容器。
1 | [root@ec95646b1a4c home]# exit |
修改主机中 /home/ceshi/test.java 文件的内容。
1 | [root@sail ceshi]# vim test.java |
重启容器。
1 | [root@sail ~]# docker start ec95646b1a4c |
查看 /home 下的文件。
1 | [root@sail ~]# docker exec -it ec95646b1a4c /bin/bash |
此时容器中的文件也更改了。
由此可见,数据卷技术实现的是双向同步。
权限设置
在使用命令方式设置卷时,还可以指定权限,以此保证数据安全。
参数
ro
(readonly):只读。rw
(readwrite):可读可写。
以数据卷只读权限启动镜像。
1 | [root@sail mysql]# docker run -it -v /home/sail:/home:ro centos /bin/bash |
新建文件测试。
1 | [root@02ef70c94920 home]# touch test.java |
容器内部该目录是没有写入权限的。
以数据卷可读可写的权限启动镜像。
1 | [root@sail mysql]# docker run -it -v /home/sail:/home:rw centos /bin/bash |
新建文件测试。
1 | [root@sail mysql]# docker run -it -v /home/sail:/home:rw centos /bin/bash |
容器内部该目录写入是没有问题的。
前面我们没有指定权限也可以写入,由此可见,数据卷默认是具有读写权限的。
具名挂载
启动镜像时只定义主机卷名称,不指定挂载目录。
1 | [root@sail mysql]# docker run -it -v my-centos:/home centos /bin/bash |
查看目前挂载的卷。
1 | # 使用 Ctrl + P + Q 不退出容器的情况下回到主机目录。 |
查看卷的详情。
1 | [root@sail mysql]# docker volume inspect my-centos |
卷挂载在 /var/lib/docker/volumes/卷名/_data
目录下。
在没有指定主机挂载目录的情况下,会默认挂载到该目录。
由于指定了卷名,所以这种方式称为具名挂载。
匿名挂载
启动镜像时只指定容器目录。
1 | [root@sail mysql]# docker run -it -v /home centos /bin/bash |
查看目前挂载的卷。
1 | [root@sail mysql]# docker volume ls |
查看卷的详情。
1 | [root@sail mysql]# docker volume inspect 159830cf55550c9a39e845c1d96aa04cc762005bc0c64d15d5066834b47df940 |
卷也是挂载在 /var/lib/docker/volumes/xxx/_data
目录下。
在没有指定主机挂载目录的情况下,会默认挂载到该目录。
由于没有指定卷名,所以这种方式称为匿名挂载。
只有指定主机目录的情况下会挂载到指定目录,否则都会挂载到默认目录。
实战
mysql数据同步
数据库中的数据极为重要,必须同步到主机,否则将会有非常大的数据丢失风险。
这里以 mysql 镜像为例演示数据同步的过程。
启动 mysql 镜像。
1 | [root@sail ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 |
其中 -e
为环境配置。安装启动 mysql 需要配置密码。
使用docker inspect查看挂载情况。
已经生成了两个目录的挂载。
查看主机同步的目录。
1 | [root@sail ~]# cd /home |
主机已经同步了容器挂载的目录。
使用数据库管理工具连接测试(这里使用 IDEA 自带的数据库工具)。