一、什么是Docker镜像
- Docker 镜像类似于虚拟机镜像,可以将它理解为一个只读的模板。
- 镜像是 Docker 三大核心概念中最重要的,自 Docker 诞生之日起镜像就是相关社区最为热门的关键词。
- Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在,Docker 会尝试先从默认镜像仓库下载(默认使用 Docker Hub 公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。
- 官方的 Docker Hub 网站已经提供了数十万个镜像供大家开放下载,地址:https://hub.docker.com/, 我们可以去这里搜索想使用的镜像,但是速度比较慢,也可以去阿里云搜索,速度较快,可惜显示的信息不全:https://cr.console.aliyun.com/cn-qingdao/instances/images
一般情况下,我们会从官网获取想使用的镜像到本地,然后启动容器进行运行;当然,我们也可以自己做制作镜像,上传保存以后使用。
二、镜像结构原理
(一)base 镜像
base 镜像有两层含义:
- 不依赖其他镜像,从 scratch 构建。
- 其他镜像可以之为基础进行扩展
base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等,以 CentOS 为例学习 base 镜像包含哪些内容
docker使用的centos也就200多M,而我们平时使用的centos则在4G左右
操作系统内核空间和用户空间组成如下:

1. kernel
kernel是内核空间,不同Linux的发行版本的内核空间基本都是一致的,占用空间也很小。
rootfs
- 内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。
- 用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。
- 对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。
而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。 - 我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。
- 不同的发行版的Linux的最主要区别就在于rootfs
2. base镜像
- base 镜像只是在用户空间与发行版一致,kernel 版本与发型版是不同的,所以,不同的发行版本的Linux的base镜像是不同的。
- 容器只能使用 Host 的 kernel,并且不能修改。所有容器都共用 host 的 kernel,在容器中没办法对 kernel 升级。如果容器对 kernel 版本有要求(比如应用只能在某个 kernel 版本下运行),则不建议用容器,这种场景虚拟机可能更合适。
(二)镜像的分层结构
- Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
- 新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
- 为什么 Docker 镜像要采用这种分层结构呢?
最大的一个好处就是 - 共享资源。
比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
那么如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?
答案:不会!因为修改会被限制在单个容器内。
(三)容器的可写层
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

三、镜像常用操作
(一) 列出镜像
命令:docker images,等价于docker image -ls
格式:docker images [OPTIONS] [REPOSITORY[:TAG]]
选项:
-
-a,--all = true | false:是否显示所有镜像,默认情况下,会隐藏中间镜像,只显示最终镜像。 -
--digests=true | false: 列出镜像的数字摘要值,默认为false -
--no-trunc:列出完整的镜像ID; -
-q,--quiet: 仅仅显示镜像ID(部分) -
-f,--filter "key=value":过滤列出的镜像,如果有多个过滤条件,就跟上多个--filter。支持的过滤如下:
- dangling(true | false):列出带有/不带tag的镜像,true表示不带;
- label:匹配指定label的镜像,如:
docker images --filter "label=com.example.version=1.0" - before:列出给定镜像之前创建的镜像,如:
docker images --filter "before=mysql:5.7" - since: 列出给定镜像之后创建的镜像;
--format formatString:使用Go模板打印出指定格式的列表。
可用的占位符有:
.ID – 镜像ID
.Repository – 镜像存储库名称
.Tag – 镜像tag
.Digest – 镜像digest
.CreatedSince – 从镜像创建到现在过去的时间
.CreatedAt – 镜像创建的时间
.Size – 镜像硬盘占用大小
如:docker images --format "{{.ID}}: {{.Repository}}"f6509bac4980: mysql a6d30d268719: foxiswho/rocketmq fd24e9fd1018: foxiswho/rocketmq 9f38484d220f: centos 7df83bb6e638: styletang/rocketmq-console-ng
结果显示的内容包括:
- REPOSITORY:镜像所在仓库,如mysql表示仓库为mysql;
- TAG:镜像标签,一般用来标志版本,当然,也可以根据自己的需要标记,跟内容无关,如:5.7
- IMAGE ID:镜像ID,唯一标识镜像, 如果两个镜像的ID相同, 说明它们实际上指向了同一个镜像, 只是具有不同标签名称而已。
- CREATED :创建时间, 说明镜像最后的更新时间。
- SIZE:镜像大小,优秀的镜像往往体积都较小
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 f6509bac4980 2 weeks ago 373MB
注意:我们也可以基于名称和tag来查找镜像,如:docker images mysql 、 docker images mysql:5.7 等等
(二)给镜像添加标签
命令:docker tag
格式:docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
我们可以使用docker tag给已有的镜像添加一个标签,不够这个镜像和之前的镜像ID是一样的,也就是说,这个tag相当于取了一个别名而已,也类似于软连接,如:docker tag mysql:5.7 db:mysql-5.7, 效果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
db mysql-5.7 f6509bac4980 2 weeks ago 373MB
mysql 5.7 f6509bac4980 2 weeks ago 373MB
如果我们删除db:mysql-5.7,那么实际上删除的是这个标签;
(三)查看镜像详情
命令:docker [image] inspect
格式: docker [image] inspect [OPTIONS] IMAGE [IMAGE...]
会获取该镜像的详细信息,包括制作者 、 适应 架构、各层的数字摘要等。
选项:
-f,--format formatstring:对结果进行格式化,如:docker inspect mysql:5.7 --format "{{.RootFS}}", 这里面可以写结果JSON里面的key。
(四)查看镜像历史
命令:docker [image] history
格式:docker [image] history [OPTIONS] IMAGE
选项:
-H:人性化显示
如:docker history mysql:5.7
(五)搜索镜像
命令:docker search
格式:docker search [OPTIONS] keyword
选项:
--limit limit:指定最多显示的镜像数量--no-trunc:不截断输出--format formatstr:使用go模板格式化输出
支持的占位符有:
.Name:镜像名
.Description:镜像描述
.StarCount:星的数量,类似于被赞的数量
.IsOfficial:是否是官方的
.IsAutomated:是否是自动化的-f,--filter filterstr:过滤输出的结果,支持如下过滤
- stars=num:找出星数不低于num的,如 :
--filter stars=3 - is-automated = true | false:找出是/不是自动构建的;
- is-official=true | false : 找出是/不是官方的;
示例:
docker search --filter is-official=true --filter stars=1000 --format "{{.Name}}----{{.StarCount}}" nginx
结果如下:
nginx----11784
(六)下载镜像
命令:docker [image] pull
格式:docker [image] pull [OPTIONS] NAME[:TAG|@DIGEST]
选项:
-a, --all-tags=trueifalse:是否下载仓库的所有镜像,默认为false--disable-content-trust:是否跳过镜像内容校验,默认为true;
- 下载最新镜像:docker pull mysql,等价于docker pull mysql:latest
- 指定tag:docker pull mysql:5.7
- 指定仓库中心
默认情况下,都是从docker hub上下载的镜像,也就是说,上面的命令等价于:docker pull registry.hub.docker.com/mysql:5.7,如果需要从非官方下载,需要指定完整的仓库地址,如从163下载:docker pull hub.c.163.com/public/mysql:5.7 - 终止下载:ctrl+C就可以结束下载。
(七)删除镜像
命令:docker rmi 等价于:docker image rm
格式:docker rmi [OPTIONS] IMAGE [IMAGE...]
选项:
-f, --force:强制删除,即使有容器依赖它(不加的话,如果有容器依赖则不能删除)--no-prune:不要清理未带标签的父镜像
可以使用下面两种方式进行删除:
- 使用镜像名:tag方式删除,如:docker rmi mysql:5.7
- 使用镜像ID删除,如:docker rmi -f fce289e99eb
删除的时候会打印各层的信息
小技巧:删除所有镜像可以使用 docker rmi -f $(docker images -qa)
(八)清理镜像
使用Docker一段时间后, 系统中可能会遗留一些临时的镜像文件, 以及一些没有被使 用的镜像, 可以通过docker image prune命令来进行清理
命令:docker image prune
格式:docker image prune [OPTIONS]
选项:
-a, --all:清除所有没有使用的镜像,不指定的话,只会删除不带tag的-f, --force:不用等待确认,直接清除--filter filter:按照过滤条件清除
支持的过滤条件有:
- label:根据label清除,可以有:
(label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>) - until timestamp:清除指定时间戳之前的镜像,如:
docker image prune -a --force --filter "until=2017-01-04T00:00:00"
也可以写作:"until=240h"这种格式
(九)创建镜像
创建镜像有三种方式:基于已有镜像的容器创建、 基千本地模板导入、 基于
Dockerfile 创建。
基于已有容器创建
命令:docker [container] comit
格式:docker [container] commit [OPTIONS] CONTAINERID [REPOSITORY[:TAG]]
选项:
-a, --author string:镜像创建者-c, - -change=[]:通过命令进行更改,数组,如:--change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80"-m, --message string:当前提交的消息-p, --pause:在提交的时候,暂停当前容器的运行
使用示例:
在ununtu上面创建一个文本文件test.txt,然后创建出一个新的镜像
//先模拟运行了一个容器
docker run -it ubuntu
echo "hello,ubuntu">test.txt
exit (退出之前记住提示中的容器编号,就是root@后面的内容)
//对容器进行commit,制作镜像
docker commit -m "add a test file to ubuntu" -a "firewolf" 22f745ca8f24 ubuntu:test1.1
//查看生成的镜像,效果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu test1.1 766b2be8155e About a minute ago 64.2MB
基于镜像模板导入
命令:docker [container] import
格式:docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
选项:
-c, --change list:更改命令-m, --message string:提交信息
使用示例:
- 导入远程的:
docker import http://example.com/exampleimage.tgz - 导入本地的(下载的或者是基于被的镜像导出的):
cat exampleimage.tgz | docker import - exampleimagelocal:new
或者是
docker import /path/to/exampleimage.tgz - 导入本地目录的
tar -c . | docker import - exampleimagedir
基于Dockerfile创建
命令:docker [image] build
格式: docker build [OPTIONS] PATH | URL | -
选项:
-f:指定dockerfile文件-t:指定tag
选项较多,其他的不是很重要
基于 Dockerfile创建是最常见的方式。 Dockerfile 是一个文本文件,利用给定的指令描 述基于某个父镜像创建新镜像的过程 。
示例:
docker build -t ubuntu:1.1
不指定-f,默认为Dockerfile
更多关于Dockerfile的内容,在专门章节讲解
(十)保存镜像到本地
我们可以把docker中的镜像保存到本地
命令:docker save 等价于 docker image save
格式:docker save [OPTIONS] IMAGE [IMAGE...]
选项:
-o, --output string:指定保存到的地址
如:docker save -o hello.tar hello-world
就会在当前目录生成一个hello.tar,这样,就可以把这个镜像传递给别人了。
(十一)从本地加载镜像
我们可以通过保存的镜像文件加载镜像到Docker中;
命令:docker load 等价于docker image load 等价于 docker load < 镜像文件
格式:docker load [OPTIONS]
选项:
-i, --input string:指定镜像文件位置
如:docker load -i hello.tar
(十二)上传镜像
命令:docker [image] push
格式:docker [image] push NAME [:TAG] | [REGISTRY_HOST [ :REGISTRY_PORT] / ]NAME [:TAG]
默认情况下,会推送到docker hub ,这需要docker账号登录,然而,比较慢,所以选择使用阿里云镜像服务,示例如下:
- 在阿里云镜像服务创建镜像命名空间和镜像仓库



点击创建即可,当然,我们也可以用云code等方式,可以自己去实验。
接下来,点击管理,即可显示对它的相关操作

- 登录阿里云Docker 中心
sudo docker login --username=firewolf_123 registry.cn-qingdao.aliyuncs.com - 推送镜像到仓库
sudo docker login --username=firewolf_123 registry.cn-qingdao.aliyuncs.com sudo docker tag [ImageId] registry.cn-qingdao.aliyuncs.com/firewolf/test-ubuntu:[镜像版本号] sudo docker push registry.cn-qingdao.aliyuncs.com/firewolf/test-ubuntu:[镜像版本号] - 使用推送到阿里云的镜像(下拉)
sudo docker pull registry.cn-qingdao.aliyuncs.com/firewolf/test-ubuntu:[镜像版本号] - 设置镜像仓库密码,否则会登录不上

不设置会出现如下错误:Error response from daemon: Get https://registry.cn-qingdao.aliyuncs.com/v2/: unauthorized: authenti - 对于上传的镜像,我们在镜像仓库列表点击名字,会看到的详细信息,比如镜像版本等等:


本文深入解析Docker镜像的概念,包括其结构原理、如何创建和管理镜像,以及镜像的分层共享机制。涵盖了镜像的下载、保存、上传等操作,适合初学者和进阶用户学习。
1213

被折叠的 条评论
为什么被折叠?



