花粉乐分享平台宣传视频
> 华为资讯 > 华为资讯 > 华为云 > 02. 一切从Image开始
02. 一切从Image开始
来源:KnockCloud
2022-06-26 15:31:37
705
管理

1.容器镜像 容器镜像是容器的模板,容器是镜像的运行实例, runtime根据容器镜像创建容器;容器镜像挂载在容器根目录下,是为容器中的应用提供隔离后执行环境的文件系统。
  • base镜像
我们希望能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件,这样的镜像我们称作base镜像;能称作base镜像的通常都是各种Linux发行版的Docker镜像,比如 Ubuntu、Debian、CentOS等,其他镜像可以以之为基础进行扩展。 注:base镜像从scratch构建,不依赖于其他镜像;scratch是Docker官方提供的一个空镜像。 Linux内核空间和用户空间 ①、实现机制: Ⅰ. Linux操作系统由内核空间和用户空间组成,其中内核空间是kernel, Linux在刚启动时会加载bootfs文件系统,启动完成之后bootfs会被卸载掉;用户空间的文件系统是rootfs, 包含/dev、/proc等目录。不同Linux发行版的区别主要就是rootfs,所以可以在同一台host上部署不同Linux发行版的base镜像。 Ⅱ. 对于base镜像来说,底层直接用Host的kernel, 自己只需要提供rootfs就行了(即打包应用及其运行所需要的所有依赖包),所以相对于虚拟机来说更加轻便。 注:base镜像在用户空间与发行版一致,但是内核的版本和Docker host主机的kernel版本一致;容器只能使用host的kernel,但是不能修改。
  • 镜像分层结构
Docker支持通过扩展现有镜像来创建新的镜像,也就是说所有镜像层联合在一起,即为一个联合文件系统,这类文件系统会把多个目录(可能对应不同的文件系统)挂载到同一个目录,对外呈现这些目录的联合,也就是说用户在容器层中只能看到最上层的文件,最终呈现出一个分层的结构; 注:联合文件系统UnionFS将所有的镜像层联合挂载到一个统一的挂载点(镜像层文件系统中不同的目录进行“合并”),最终表现为一个Linux操作系统供容器使用。 可以最大化实现资源共享:当多个镜像都是从同一个base镜像构建而来,内存中只需加载一份base 镜像,就可以为所有容器服务;通过写前拷贝COW技术来实现资源共享。 原理简单阐述就好比:当父进程 fork 子进程时,内核并没有为子进程分配内存(当然基本的进程控制块、堆栈还是需要的),而是让父子进程共享内存;当两者之一修改共享内存时,会触发一次缺页异常导致真正的内存分配(此时才会为父子进程分配独享内存)。 联合文件系统架构 1、联合文件系统实现机制: ①、首先需要内核支持OverlayFS特性; $ cat /proc/filesystems | grep overlay nodev overlay ②、创建分层的工作目录(相当于除了容器层以外的其他层); $ mkdir base $ echo "layer 1" > base/metadata $ echo "hello,docker!" > base/data $ mkdir overlay $ echo "layer 2" > overlay/metadata $ echo "hello,k8s!" > overlay/data2 ③、创建顶层目录(相当于容器层),以及OverlayFS所必需的work工作目录、文件系统挂点; $ mkdir top work point ④、将分层以overlay文件系统类型挂载到挂载点; $ mount -t overlay overlay -o lowerdir=overlay:base,upperdir=top,workdir=work point #-t:指定文件系统类型 #-o:指定挂载选项,lowerdir指定底层目录(从高层向低层指定),upperdir指定顶层目录 (也就是容器层),workdir指定工作目录 #最后指定挂载点 ⑤、在挂载点目录下可以看到联合目录,目录所处的层级是很重要的,上层的文件会覆盖同名的下层文件; #可以看到挂载点处显示出的联合目录 $ ll */* -rw-r--r-- 1 root root 14 ... base/data -rw-r--r-- 1 root root 10 ... base/metadata -rw-r--r-- 1 root root 11 ... overlay/data2 -rw-r--r-- 1 root root 10 ... overlay/metadata -rw-r--r-- 1 root root 14 ... point/data -rw-r--r-- 1 root root 11 ... point/data2 -rw-r--r-- 1 root root 10 ... point/metadata #查看具有同名的上下层文件metadata $ cat point/metadata layer 2 #内容为overlay层的metadata文件内容,而base层的metadata文件内容被覆盖 ⑥、当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层","容器层”之下的都叫“镜像层”,只有容器层是可写的,容器层下面的所有镜像层都是只读的;修改文件时同理,当在容器中修改已存在的文件时,Docker会从上往下依次在各镜像层中查找此文件,一旦找到,立即将其复制到容器层(top层),然后再修改; 此处仅做目录模拟,所以其他镜像层仍是可以写的。 #当向point目录中写入数据时,会写入到top目录(顶层目录)中 $ echo "top layer" > point/frame $ ll */* ... -rw-r--r-- 1 root root 10 ... point/frame -rw-r--r-- 1 root root 10 ... top/frame $ cat top/frame     #查看容器层写入的文件内容,即为写入到挂载点同名文件中的内容 top layer #修改point/data文件内容 $ cat point/data hello,docker! test modify #然后会在top顶层目录中新增一个同名文件,内容即为修改后的内容 $ ll */* ... -rw-r--r-- 1 root root 10 ... top/data $ cat top/data hello,docker! test modify #查看底层base/data文件,发现内容并未改变 $ cat base/data hello,docker! ⑦、当在容器中删除文件时, Docker 也是从上往下依次在镜像层中查找此文件。找到后,UnionFS会在容器层创建一个"whiteout"文件将被删除的文件进行遮挡,并且在容器层会创建一个同名的、主次设备号均为0的字符设备,文件不会被删除(空间不一定会被回收);如果制作 image 时使用到了一些关键的信息(用户名、密码等),则需要在所在层删除,不然这些信息依然会存在于 image 中。 c--------- 1 root root 0, 0 ... top/data
  • 在线获取镜像
❶、安装docker-ce:以Centos系统为例,首先要获取docker-ce的yum源,此处使用的是华为云提供的repo;然后安装docker-ce $ wget -O /etc/yum.repos.d/docker-ce.repo https://img.hflfx.com/pic/wgjhkkt0yaw $ sudo sed -i 's download.docker.com repo.huaweicloud.com/docker-ce ' /etc/yum.repos.d/docker-ce.repo #修改获取镜像的地址 #如果是Centos8版本的系统,则可以参照之前的《00:先让Docker跑起来》文章。 ❷、配置Docker镜像加速器:如果使用公共镜像仓库,由于是在国外网速限制,须要通过镜像加速站来获取镜像,以下以华为云平台镜像加速站配置为例(需提前注册华为云账号,并在控制台中找到容器镜像服务) 当镜像仓库使用"https",使用时则需要先进行登录验证,然后才能从镜像仓库拉取镜像;当镜像仓库使用"http"(或私有镜像仓库,直接使用IP地址),则不需要,可以直接拉取使用。 $ vim /etc/docker/daemon.json #如果该文件没有,则需要手动创建 { "registry-mirrors": ["https://******.myhuaweicloud.com"] } $ systemctl daemon-reload #重新加载daemon服务器配置文件 $ systemctl restart docker.service ❸、首先须要登录获取访问权限,u是用户,p是密码(在个人控制台自动生成) $ docker login -u *** -p *** swr.cn-north-1.myhuaweicloud.com ❹、拉取镜像 $ docker pull httpd:2.4 2.4: Pulling from library/httpd ...Pull complete Status: Downloaded newer image for httpd:2.4 $ docker image list REPOSITORY TAG IMAGE ID CREATED SIZE httpd 2.4 683a7aad17d3 2 months ago 138MB
  • 分析镜像分层
可以使用dockerviz工具来分析Docker image。 1、首先将dockviz.tar包(从百度网盘中下载)上传到镜像仓库; 链接:https://pan.baidu.com/s/1C318yk45Mnh0jjyiC1hE3g 提取码:rc5r $ docker load -i dockviz.tar 2、然后在 /etc/bashrc文件中最后一行添加命令别名,保证每次执行dockviz命令时都会临时运行一个dockerviz的容器来执行相应的动作;(退出重新登录后生效) $ alias dockviz="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock dockviz:latest" 3、执行以下命令,让镜像文件以分层的形式保存在images.png图片中 #将所有的镜像信息以png的格式保存到images.png文件中 $ dockviz images -d | dot -Tpng -o images.png #最后可以下载到Windows本地查看图片2. 构建镜像 Docker提供了两种构建镜像的方法:docker commit命令与Dockerfile构建文件
  • docker commit命令
docker commit,实际上是在容器运行起来后,把最上层的“可读写层”,加上原先容器镜像的只读层,打包组成了一个新的镜像;一般包含三个步骤:运行容器;修改容器;将容器保存为新的镜像,过程更加直观。 注:Docker并不建议用户通过这种方式构建镜像,原因是无法对镜像进行审计,存在安全隐患。 实现步骤:使用commit命令构建镜像 ❶、运行一个Centos 7 的base镜像; $ docker run -it centos:7 # -it表示以交互的方式运行容器,并进入到容器 Unable to find image 'centos:7' locally #由于已登录到华为云,将从huaweicloud.com拉取镜像 ...: Pull complete ❷、在base镜像中安装软件,并退出; $ vim bash: vim: command not found #base镜像中没有安装vim工具 $ yum install vim -y   #使用yum安装vim工具 ... Complete! $ rpm -qa | grep vim   #检查已正常安装vim工具 vim-common... $ exit ❸、使用commit命令将修改后的centos7容器封装成一个名为my_iamge的镜像。 $ docker ps -a CONTAINER ID IMAGE ... NAMES ff9a563e9fd8 centos:7 ... vibrant_sammet $ docker commit vibrant_sammet my_image #直接将容器commit成名为my_image的镜像 $ docker image list REPOSITORY TAG IMAGE ID CREATED SIZE my_image latest cfdce8636c33 39 seconds ago 366MB centos 7 8652b9f0cb4c 4 months ago 204MB ❹、验证:可以看到my_image镜像比centos:7镜像多了一层镜像 # docker history指令会显示镜像的分层结构,并且按照镜像层的顺序由上至下排列 $ docker history centos:7 IMAGE CREATED BY SIZE 8652b9f0cb4c /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB $ docker history my_image:latest IMAGE CREATED BY SIZE cfdce8636c33 /bin/bash 162MB #安装了vim编辑器8652b9f0cb4c /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
  • Dockerfile
dockerfile是一个文本文件,记录着镜像构建的所有步骤,但是底层也是使用docker commit 一层一层构建的, ①、dockerfile构建镜像原理: Ⅰ. 从base 镜像运行一个容器; Ⅱ. 执行一条指令,对容器做修改; Ⅲ. 执行类似docker commit 的操作,生成一个新的镜像层; Ⅳ. Docker 再基于刚刚提交的镜像运行一个新容器(原容器会被删除); Ⅴ . 重复 Ⅱ~Ⅳ 步,直到Dockerfile 中的所有指令执行完毕。 ②、根据下表字段创建一个dockerfile文件;当使用build指令时,需要指定某个目录为build context,build context 为镜像构建提供所需要的文件或目录;Docker默认会从build context 中查找Dockerfile文件,所以不要将不期望存在的文件放到build context目录下。 Dockerfile常用指令 ③、RUN、CMD、ENTRYPOINT区别 RUN、CMD和ENTRYPOINT都是用来运行命令的,命令执行格式可以分为shell和Exec两种: shell:直接调用底层的shell(如 /bin/bash)来执行命令,其格式为 RUN/CMD/ENTRYPOINT <command>ENV name Cloud #指定环境变量name的值为 Cloud ENTRYPOINT echo "Hello, $name" #启动容器后输出即为 Hello,Cloud Exec:直接调用 [command],但是不会被底层的shell解析,其格式为 RUN/CMD/ENTRYPOINT ["executable", "paraml", "param2", ...]ENV name Cloud #指定环境变量name的值为 Cloud ENTRYPOINT ["/bin/echo","Hello,$name"] #启动容器后输出即为 Hello,$name ❶ RUN:指令通常用于给容器安装应用和软件包;Dockerfile中常常包含多个RUN指令,在当前镜像的顶部执行命令,完成一条RUN指令之后就会创建新的镜像层,也就是说不同的RUN指令代表了不同的镜像层。 ❷ CMD:指令允许用户指定容器的默认执行的命令,因为容器是为应用而生的,启动容器最终目的是启动应用(或者是执行一个循环语句)以避免容器启动后无应用而退出(状态为exited),在容器启动且docker run没有指定其他命令时运行 注:如果docker run指定了其他命令,CMD指定的默认命令将被忽略;如果Dockerfile中有多个CMD指令,只有最后一个CMD有效。 ❸ ENTRYPOINT:指令可让容器以应用程序或者服务的形式运行,和CMD不同的地方在于ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。 ④、实现步骤:使用Dockerfile构建镜像 ❶、构建前需要准备build context目录、准备好base镜像 $ pwd #新建一个dockerfile目录作为build context /root/dockerfile $ ls #目录下保存base镜像,dockerfile文件以及需要的file2 CentOS-7-x86_64-docker.img.tar.xz dockerfile file2 ❷、写一个dockerfile文件 注:可以从一个空镜像开始,也可以从base镜像开始,如果从空镜像开始,必须指定进入到容器之后的shell,如Centos系统是bash shell $ vim dockerfile FROM scratch #指定从一个空镜像开始 MAINTAINER KnockCloud #指定镜像作者 ADD CentOS-7-x86_64-docker.img.tar.xz / #添加一个Centos系统的base镜像 CMD ["/bin/bash"] #必须指定进入到容器之后使用的shell WORKDIR /testdir #用于指定进入到容器之后的目录(如果没有会创建) RUN touch file1 COPY file2 . #将file2拷贝到容器的 /testdir 目录下,注意file2文件必须提前在docker context中存在 ENV WELCOME "You are in my container,welcome!" ❸、使用dockerfile创建一个名为first-dockerfile的镜像 #这里的"."表示dockerfile所在的目录,在本实验中是当前目录 $ docker build -t first-dockerfile . #docker会将build context中的文件发送给docker daemon Sending build context to Docker daemon 36.29MB Step 1/8 : FROM scratch #从一个空镜像开始 ---> Step 2/8 : MAINTAINER Docker ---> Running in b9617c3257db Removing intermediate container b9617c3257db ---> db4a3a49178d #添加一个Centos系统的base镜像到容器的根目录下 Step 3/8 : ADD CentOS-7-x86_64-docker.img.tar.xz / ---> 5ed7df8f5c30 #指定进入到容器之后使用bash shell(必须指定) Step 4/8 : CMD ["/bin/bash"] ---> Running in d5bc15e94c2c Removing intermediate container d5bc15e94c2c ---> 7695f1da0b99 Step 5/8 : WORKDIR /testdir #指定进入容器之后的工作目录 ---> Running in 02bf878461a7 Removing intermediate container 02bf878461a7 ---> 8bee16518a33 Step 6/8 : RUN touch file1 ---> Running in 12b2f04b31ed Removing intermediate container 12b2f04b31ed ---> abdb9cbd61c7 Step 7/8 : COPY file2 . #这里的"."表示上面指定的工作目录 ---> 2d32516ab12f Step 8/8 : ENV WELCOME "You are in my container,welcome!" ---> Running in 6e6857f7ad1b Removing intermediate container 6e6857f7ad1b ---> 29e652e510d5 Successfully built 29e652e510d5 Successfully tagged first-dockerfile:latest ❹、验证结果 $ docker run -it first-dockerfile bash-4.2# pwd #查看进入容器之后的工作目录 /testdir bash-4.2# ls #查看工作目录下的文件 file1 file2 bash-4.2# cat file2 #从docker context拷贝过来的file2文件 It's worked! bash-4.2# echo $WELCOME #设置的变量值 You are in my container,welcome!3.镜像仓库
  • 镜像命名
可以使用docker tag给镜像重命名,实际上一个特定镜像的名字由两部分组成: repository 和 tag ;tag常用于描述镜像的版本信息,如果执行 docker build 时没有指定 tag, 会使用默认值 latest 镜像命名格式为:[image name] = [repository]: [tag] 注:repository 的完整格式为:[registry-host]: [port]/[namespace]/httpd,只有使用公共Registry且已经登录的时候,registry-host:[port]/[namespace]才可以省略。
  • 搭建本地Registry
①、启动Registry容器,然后将其映射到主机的5000端口,镜像存储位置映射到主机本地目录; $ docker run -d -p 5000:5000 #指定端口映射,将主机端口映射给容器(网络章节会详解) -v /myregistry:/var/lib/registry #指定存储位置映射(存储章节会详解) registry:2.7 ...Pull complete . ②、修改daemon.json文件中的镜像仓库地址,如果地址是私有仓库的地址,应按照registry-host:[port]的格式修改地址 #设置以非安全模式(即非HTTPS)连接到本仓库$ cat /etc/docker/daemon.json { "insecure-registries": ["192.168.1.11:5000"] #本机地址:映射端口号 } ③、通过 docker tag 重命名镜像,使之与registry相匹配 #username可以任意但不能包含大写字母 $ docker tag httpd:2.4 192.168.1.11:5000/docker/httpd:2.4 ④、通过 docker push 上传镜像 $ docker push 192.168.1.11:5000/docker/httpd:2.4 The push refers to repository [192.168.1.11:5000/docker/httpd] ... Pushed $ pwd /myregistry/docker/registry/v2/repositories $ ls #镜像文件保存在本地指定的用户文件夹里 docker ⑤、验证,尝试从私有镜像仓库拉取镜像 注:拉取镜像时必须指定镜像仓库和用户名,不然就会到docker官方网站上去拉取了 #到私有镜像仓库拉取镜像时要补全镜像的tag $ docker pull 192.168.1.11:5000/docker/httpd:2.4 2.4: Pulling from docker/httpd Digest: sha256:88fb0fb4b406f944e220f082b5a56d1f0e8471abc45fd... Status: Downloaded newer image for 192.168.1.11:5000/docker/httpd:2.4 192.168.1.11:5000/docker/httpd:2.4 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.1.11:5000/docker/httpd 2.4 683a7aad17d3 2 months ago 138MB
  • 命令补充
docker rmi :用于删除host上的镜像,如果容器正在使用,那么就必须先删除容器,然后才能删除镜像。 docker search:可以无须打开浏览器,在命令行中就可以搜索公共Registry中的镜像,可以根据不同的tag来拉取镜像。 docker save:将某个镜像保存为tar包,命令格式为: docker save <IMAGE_NAME> -o <TAR_NAME> docker load:将镜像tar包加载为镜像,格式为: docker load -i <TAR_NAME>

花粉社群VIP加油站

3
点赞
赏礼
赏钱
0
收藏
免责声明:本文仅代表作者个人观点,与花粉乐分享无关。其原创性以及文中陈述文字和内容未经本网证实,对本文以及其中全部或者 部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
凡本网注明 “来源:XXX(非花粉乐分享)”的作品,均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对 其真实性负责。
如因作品内容、版权和其它问题需要同本网联系的,请在一周内进行,以便我们及时处理。
QQ:2443165046 邮箱:info@hflfx.com
关于作者
肉嘟嘟(蜂界传说)
文章
499
主题
1
关注
0
粉丝
1
点击领取今天的签到奖励!
签到排行
随手拍
54个圈友 0个话题
华为手机随手拍,记录生活点滴之美好
华为P30pro
51个圈友 0个话题
这里是华为P30pro手机交流圈,欢迎华为P30pro用户进群交流
体验官
60个圈友 2个话题
华为花粉体验官,体验官专属的交流群
登录后查看您创建的圈子
登录后查看您创建的圈子
所有圈子
杭州互联网违法和不良信息举报平台 网络110报警服务 浙ICP备17046585号
3
0
分享
请选择要切换的马甲:

个人中心

每日签到

我的消息

内容搜索