彻底学明白,docker镜像的原理
我们在获取redis镜像的时候,发现下载了多行信息,最终又得到了一个完整的镜像文件。
我们使用的centos7系统长什么样?
我们一直以来,使用虚拟机,安装的系统是一个完整的系统,包括2部分
- linux内核,作用是提供操作系统的基本功能,和机器硬件交互。
- centos7发行版,作用是提供软件功能,如yum安装包管理等。
因此,linux内核 + centos发行版,就组成了一个操作系统,让我们用户使用。
是否有一个办法,可以灵活的替换发行版,让我们使用不同的系统?
docker就实现了这个功能,技术手段就是docker images
查看系统的两大命令
- 查看发行版本
cat /etc/redhat-release
- 查看内核版本
uname -r
快速实践,使用docker来切换不同的发行版,内核使用的都是宿主机的内核
利用docker获取不同的发行版镜像
docker pull centos:7.8.2003
docker pull ubuntu
确认当前宿主机的发行版
cat /etc/redhat-release
运行centos7.8.2003发行版,且进入容器内
docker run -it afb6fca791e0 bash
参数解释 :
- -i 交互式命令操作
- -t 开启一个终端
- afb6fca791e0是镜像的ID
- bash 进入容器后,执行的命令.
进入到正在运行的容器内,命令是Docker exec
docker exec -it afb6fca791e0 bash
查看容器内的发行版本
cat /etc/redhat-release
运维小王,想玩一玩Ubuntu了,直接去运行Ubuntu镜像即可。
docker run -it ubuntu bash
查看当前容器内的发行版
cat /etc/lsb-release
理解什么是docker镜像
docker images搜索地址 :
https://hub.docker.com/_/centos?tab=tags&page=1&ordering=last_updated
一个完整的docker镜像可以创建出docker容器,例如一个centos:7.8.2003
镜像文件,我们获取的是centos7这个发行版,这个镜像文件是不包含在linux内核中的。
docker的架构
镜像就是一个【发行版】的作用,你需要准备好linux内核,然后上层使用不同的【发行版】就好了,这样你可以自由的使用各种版本系统,兼容多种环境。
Union File System:docker 通过联合文件系统,将上述不同的每一层,整合为一个文件系统,为用户隐藏了多层的视角。
小节:
- 当通过image启动容器时,docker会在该image最顶层,添加一个读写文件系统作为容器,然后运行该容器。
- docker镜像本质是基于UnionFS管理的分层文件系统。
- docker镜像为什么才几百兆?
因为Docker镜像只有rootfs和其他镜像层,然后公用宿主机的linux内核(bootfs),因此很小。
- 为什么下载一个docker的nginx镜像,需要133MB?Nginx安装包不是才几兆吗?
因为Docker的nginx镜像是分层的,nginx安装包的确就几兆,但是一个用于运行nginx的镜像文件,依赖于父镜像(上一层)和基础镜像(发行版),所以下载的nginx镜像才有一百多兆。
Docker镜像定义
我们如果自定义镜像,Docker镜像不包含linux内核,和宿主机共用。
我们如果想要定义一个 mysql5.6 镜像,我们会这么做
- 获取基础镜像,选择一个发行版平台(Ubuntu、Centos)
- 在Centos镜像中安装mysql5.6软件
导出镜像,可以命名为 mysql:5.6镜像文件。
在这个过程,我们可以感觉出这是一层一层的添加的,docker镜像的层级概念就出来了,底层是centos镜像,上层是mysql镜像,centos镜像属于父镜像。
Docker镜像是在基础镜像之后,然后安装软件,配置软件,添加新的层,构建出来。
这种现象在学习Dockerfile构建时候,更为清晰。
Docker 为什么分层镜像
镜像分析一大好处就是共享资源,例如有多个镜像都来自于同一个base镜像,那么docker host只需要存储一份Base镜像。
内存里也只需要加载一份host,即可为多个容器服务。
即使多个容器共享一个Base镜像,某个容器修改了Base镜像的内容,例如修改 /etc/
下配置文件,其他容器的 /etc/
下内容是不会被修改的,修改动作只限制在单个容器内,这就是容器的写入时赋值特性(Copy-on-write)。
可写的容器层
当容器启动后,一个新的可写层被加载到镜像的顶部,这一层通常被称为容器层
,容器层
下层都称为镜像层。
所有对容器的修改动作,都只会发生在容器层里,只有容器层是可写的,其余镜像层都是只读的。
文件操作 | 说明 |
---|---|
添加文件 | 在容器中创建文件时,新文件被添加到容器层中 |
读取文件 | 在容器中读取某个文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存 |
修改文件 | 在容器中修改已存在的文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之 |
删除文件 | 在容器中删除文件时,Docker也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除惭怍。(只是记录删除操作) |
只有当需要修改时才复制一份数据,这种特性被称作Copy-on-Write
。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们提出的问题:容器层记录对镜像的修改,所有的镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
Docker镜像的内容
Docker镜像层级管理方式大大便捷了Docker镜像的分发和存储。Docker Hub是为全世界的镜像仓库。
- Docker镜像代表一个容器的文件系统内容。
- 镜像层级技术属于
联合文件系统
- 容器是一个动态的环境,每一层镜像里的文件都属于静态内容。
- dockerfile里的ENV、VOLUME、CMD等内容都会落实到容器环境中。
UnionFS
Docker镜像的实际使用
超哥在进行开发,安装很多第三方的工具,比如 etcd、kafka、mysql、nginx 等等。而开发机不想乱搞当前机器的环境,此时可以使用 Docker。
比如我们想要安装一个Nginx:
- 下载安装Docker工具。
- 获取该软件的Docker镜像,下载Nginx镜像,docker pull nginx。
- 运行该镜像,然后就启动了一个容器,这个Nginx服务就运行在容器中。
- 停止容器,删除该镜像,你的电脑上就好像没有使用Nginx一样。
搜索镜像
搜索镜像
docker search 镜像名:tag tag就是具体的标签版本
docker search centos
获取镜像
镜像托管仓库,好比yum源一样。 默认的docker仓库是 docker hub,它有大量优质的镜像,以及用户自己上传的镜像。比如 vim、nginx等等。
查看本地的镜像文件有哪些
docker images
docker image ls
下载docker 镜像
docker pull centos #默认的是centos:lastest
docker pull centos:7.8.2003
查看docker镜像的存储路径
docker info |greo Root
ls /var/lib/docker/image/overlay2/imagedb/content/sha256/ -l
该文件作用是
记录 镜像 和容器的配置关系
使用不同的镜像,生成容器
docker run -it --rm centos bash
-it:开启一个交互式的终端
–rm:容器退出时删除该容器
查看镜像
docker images
查看具体的镜像
docker images centos
指定具体的tag
docker images centos:7.8.2003
只展示镜像ID
docker images -q
格式化显示镜像,这是docker的模板语
docker images --format "{{.ID}}--{{.Repository}}"
删除镜像
下载hello-world镜像
docker pull hello-world
根据镜像的 ID、名字、摘要
等删除镜像,被删除的镜像不得有依赖的容器记录。被删除的镜像,不得有依赖的容器记录。
1.根据镜像名称删除
docker rmi hello-world
2.根据镜像ID删除
docker rmi f1635b8377e5
3.指定ID的千3位进行删除
docker rmi f16
4.批量删除镜像,慎用
docker rmi `docker images -aq`
批量删除容器
docker rmdocker ps -aq
镜像其他操作
1.导出镜像
docker image save centos:7.8.2003 > /opt/centos7.8.2003.tgz
2.导入镜像
docker load -i /opt/centos7.8.2003.tgz
7.查看Docker服务的信息
docker info
8.查看镜像详细信息
docker image inspect 镜像ID
docker image inspect 镜像ID前3位