『 云原生·Docker』Docker镜像分层与Docker镜像操作(二)

发布于:2022-11-29 ⋅ 阅读:(497) ⋅ 点赞:(0)

系列文章目录

本系列主要分为以下六大部分,正在更新中,尽请期待!

🚩点击关注本专栏


提示:已经更新的或正在更新的文章前面打勾了哈!


前言

镜像是Docker三大核心概念中最重要的,自 Docker诞生之日起镜像就是docker社区最为热门得关键词。

那么镜像为什么会有如此高的热度呢?

一、镜像分层

1.Base镜像

Linux 操作系统由内核空间和用户空间组成,如下图所示:
在这里插入图片描述

内核空间是 kernel,用户空间的文件系统是 rootfs。

对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。

而对于一个精简的 OS来说,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。

相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到10MB。我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。

base 镜像提供的是最小安装的 Linux 发行版,支持运行多种 Linux OS

所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu、Debian、CentOS 等。

不同 Linux 发行版的区别主要就是 rootfs。

比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包,而 CentOS 7 使用 systemd和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。

所以 Docker 可以同时支持多种 Linux 镜像,模拟出多种操作系统环境。

2.镜像的分层结构

Docker 支持通过扩展现有镜像来创建新的镜像。

实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
在这里插入图片描述
我们可以镜像可以分层很多个layer,并且他们都有大小和ID,我们可以看到这里有4个layer ID号,最终这个镜像是由他们layer组合而成,并且这个镜像它是只读的,它不能往里面写数据,如果想写数据怎么办呢?

我们会在镜像上启一层contain layer,其实就是相当于把镜像启动成一个容器,那么在容器这一层,我们是可写的。Copy-on-Write(写时拷贝,按需拷贝的机制)

写时复制的思想(摘录自维基百科):

写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(privatecopy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被建立,因此多个调用者只是读取操作时可以共享同一份资源

下载的时候只会下载子镜像最上面的一层,因为其它层已经有了,那么它可以做到一个节约空间的作用。

新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

镜像分层最大的一个好处就是共享资源
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器Copy-on-Write 特性。

二、创建镜像

1.基于已有镜像的容器

创建 Docker镜像的第一种方法是使用 docker commit命令。

可以将此想象为我们是在往版本控制系统里提交变更。我们先创建一个容器,并在容器里做出修改,就像修改代码一样,最后再将修改提交为一个新镜像。

我们修改了当前容器以后,可以把状态保存下来。这样就不用每次都创建一个新的容器,然后再次去安装。

需要注意的是,docker commit提交的只是创建容器的镜像与容器的当前状态之间有差异的部分,这使得该更新非常轻量。

练习:学习使用Commit定制一个镜像,要求学习者参照示例完成定制一个busybox:v1镜像,该镜像在busybox:latest的基础上,新增了一个hello.txt文件

# 新增了一个hello.txt文件
docker run --name container1 busybox touch hello.txt

#将对容器container1做出的修改提交为一个新镜像,镜像名为busybox:v1
docker commit container1 busybox:v1

2.基于本地模板导入

用户也可以直接从一个操作系统模板文件导入一个镜像,主要使用 docker import

要直接导入一个镜像,可以使用 OpenVZ提供的模板来创建,或者用其他已导出的镜像,或者用其他已经导出的镜像模板来创建。

附:OpenVZ模板下载地址:点击进入

例如,下载了ubuntu-18.04的模板压缩包,之后使用如下命令导入即可:

cat ubuntu-18.04-x86_64-minimal.tar.gz | docker import -ubuntu: 18.04

三、存入与载出镜像

1.存出镜像

如果要导出镜像到本地文件,可以使用 docker[ Image]save命令。

该命令支持 -o string- output string参数,导出镜像到指定的文件(stirng)中。

例如,导出本地的ubuntu:18.04镜像文件 ubuntu_18.04.tar,如下:

docker save -o ubuntu_18.04.tar ubuntu:18.04

之后,用户就可以通过复制 ubuntu18.04.tar文件将该镜像分享给他人。

2.载入镜像

可以使用 docker load将导出的tar文件再导入到本地镜像库。

支持-i string-input string选项,从指定文件(string)中读入镜像内容。

例如,从文件 ubuntu_18.04.tar导入镜像到本地镜像列表,如下所示:

docker load -i ubuntu_18.04.tar
或
docker load < ubuntu 18.04.tar

导入成功后,可以使用 docker images命令进行查看,与原镜像一致。

四、上传镜像

可以使用 docker push 命令上传镜像到仓库。

默认上传到 Docker Hub官方仓库(需要登录),用户在 Docker hub网站注册后可以上传自制的镜像。

例如,用户user上传本地的test:latest镜像,可以先添加新的标签user/test: latest,然后用docker push命令上传镜像。

#添加新的标签
docker tag test:latest user/test:latest
#上传镜像
docker push user/test:latest

第一次上传时,会提示输入登录信息或进行注册,之后登录信息会记录到本地~/. docker目录下。

看看本专栏文章有哪些吧!

本系列文章目录:

  • 『 云原生·生之门』
  • 『 云原生·前置知识』
  • 『 云原生·Docker』
  • 『 云原生·Kubernetes』
  • 『 云原生·KubeSphere』
  • 『 云原生·DevOps』

可以看出来本系列文章将会带你从-1到1的学习云原生的,一起加油吧!

总结

镜像是使用 Docker的前提,也是最基本的知识。所以大家一定要熟练镜像得相关基本操作,在后续章节,笔者将继续介绍 Docker镜像的操作技巧。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到