第02篇 Docker镜像

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

一、什么是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 镜像有两层含义:

  1. 不依赖其他镜像,从 scratch 构建。
  2. 其他镜像可以之为基础进行扩展
    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

    支持的过滤如下:

  1. dangling(true | false):列出带有/不带tag的镜像,true表示不带;
  2. label:匹配指定label的镜像,如:docker images --filter "label=com.example.version=1.0"
  3. before:列出给定镜像之前创建的镜像,如:docker images --filter "before=mysql:5.7"
  4. 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:过滤输出的结果,支持如下过滤
  1. stars=num:找出星数不低于num的,如 : --filter stars=3
  2. is-automated = true | false:找出是/不是自动构建的;
  3. 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;
  1. 下载最新镜像:docker pull mysql,等价于docker pull mysql:latest
  2. 指定tag:docker pull mysql:5.7
  3. 指定仓库中心
    默认情况下,都是从docker hub上下载的镜像,也就是说,上面的命令等价于:docker pull registry.hub.docker.com/mysql:5.7,如果需要从非官方下载,需要指定完整的仓库地址,如从163下载:docker pull hub.c.163.com/public/mysql:5.7
  4. 终止下载:ctrl+C就可以结束下载。

(七)删除镜像

命令:docker rmi 等价于:docker image rm
格式:docker rmi [OPTIONS] IMAGE [IMAGE...]
选项:

  • -f, --force:强制删除,即使有容器依赖它(不加的话,如果有容器依赖则不能删除)
  • --no-prune:不要清理未带标签的父镜像

可以使用下面两种方式进行删除:

  1. 使用镜像名:tag方式删除,如:docker rmi mysql:5.7
  2. 使用镜像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:按照过滤条件清除
    支持的过滤条件有:
  1. label:根据label清除,可以有:(label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>)
  2. 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账号登录,然而,比较慢,所以选择使用阿里云镜像服务,示例如下:

  1. 在阿里云镜像服务创建镜像命名空间和镜像仓库
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    点击创建即可,当然,我们也可以用云code等方式,可以自己去实验。
    接下来,点击管理,即可显示对它的相关操作
    在这里插入图片描述
  2. 登录阿里云Docker 中心
    sudo docker login --username=firewolf_123 registry.cn-qingdao.aliyuncs.com
  3. 推送镜像到仓库
    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:[镜像版本号]
    
  4. 使用推送到阿里云的镜像(下拉)
    sudo docker pull registry.cn-qingdao.aliyuncs.com/firewolf/test-ubuntu:[镜像版本号]
  5. 设置镜像仓库密码,否则会登录不上
    在这里插入图片描述
    不设置会出现如下错误:
    Error response from daemon: Get https://registry.cn-qingdao.aliyuncs.com/v2/: unauthorized: authenti
    
  6. 对于上传的镜像,我们在镜像仓库列表点击名字,会看到的详细信息,比如镜像版本等等:
    在这里插入图片描述
    在这里插入图片描述
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值