百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Docker工具的使用方法进阶-关于镜像

wptr33 2025-03-26 17:48 48 浏览

承接上篇的docker简介,实际上,镜像(image)其实就是容器(container)的模板,容器都是通过镜像创建的,所以镜像中包含启动容器所需要的所有文件系统结构和内容。简单来讲,镜像是一个特殊的文件系统,它提供了容器运行时所需的程序、软件库、资源、配置等静态数据。即镜像是只读的,其不包含任何动态数据,镜像在被构建后,其内容也不会再被改变。

关于docker镜像的操作常用的主要包括:拉取、查询、重命名、删除、构建,下面我们将对这些操作逐一进行讲解。

(1)拉取镜像

docker拉取镜像的方法格式如下:

docker pull [Registry]/[Repository]/[Image]:[Tag]
  • Registry 为注册服务器,Docker 默认会从 http://docker.io 拉取镜像,如果你有自己私有的镜像仓库,可以把 Registry 替换为自己的注册服务器。
  • Repository 为镜像仓库,通常把一组相关联的镜像归为一个镜像仓库,library为 Docker 默认的镜像仓库。
  • Image 为镜像名称。
  • Tag 为镜像的标签,如果你不指定拉取镜像的标签,默认为latest。

例如,我们需要获取一个 busybox 镜像,可以执行以下命令:

$ docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
61c5ed1cbdf8: Pull complete
8lacjeddcbf59: Pull complete
Digest: sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest

这里我们可以注意到几个问题:首先就是我们pull直接使用的是 【docker pull Image】这样的格式,没有添加Registry、Repository和Tag。那么也就是说本次拉取我们是从默认服务器【http://docker.io】和默认仓库【library】拉取的。而且,在没有指定tag标签的情况下会默认使用latest【Using default tag: latest】

*注意,特别不建议在生产环境使用默认的 latest 镜像标签,因为获取这样的镜像会跟踪随着最新版本的变化而变化,比如今天刚刚拉取的镜像版本是1.0的,突然版本更新到2.0 了,此时服务器上的该镜像也会自动更新为2.0,然而在生产环境中稳定低错误才是关键,所以不推荐使用默认标签 latest

其次我们可以看到镜像是“多层存储结构“,所以下载其实是一层层下载而并不是单一的文件。在下载过程中,每一层都会有一个12位的索引 ID 做标识,形如【61c5ed1cbdf8:Pull complete】。下载完成后,最终会有一个 sha256 的识别号 Digest 俗称摘要来确保下载的一致性。

(2)查看镜像

Docker 镜像查看使用docker images或者docker image ls命令。

使用docker images命令列出本地所有的镜像。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              4bb46517cac3        9 days ago          133MB
nginx               1.15                53f3fd8007f7        15 months ago       109MB
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

如果我们想要查询指定的镜像,可以使用docker image ls命令来查询。

$ docker image ls busybox
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

当然你也可以使用docker images命令列出所有镜像,然后使用grep命令进行过滤:

$ docker images |grep busybox
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

在上面拉取镜像时我们提到过,我们拉取镜像时没有指定服务器和仓库。所以我们注意到我们的镜像名就是简单的【busybox】。而如果我们拉取的时候指定了服务器和仓库的话,那么我们通过【docker images】看到的结果就不一样了:

$ docker pull registry.hepantec.com/private_repo/busybox:1.2.2
$ docker images
REPOSITORY                                                       TAG       IMAGE ID           CREATED          SIZE
nginx                                                                   latest   4bb46517cac3     9 days ago       133MB
nginx                                                                   1.15     53f3fd8007f7      15 months ago 109MB
registry.hepantec.com/private_repo/busybox    1.2.2    018c9d7b792b    3 weeks ago     1.22MB

(3)镜像重命名

有时候会因为任务需要特定的镜像做统一管理,就可以用 docker tag 命令为本地任意镜像添加新的标签,即所谓的镜像重命名。

$ docker tag busybox:latest mybusybox:latest

所以镜像重命名可以实现:自定义镜像名称或者推送镜像到其他镜像仓库。docker tag的命令格式为【docker tag SOURCE_IMAGE TARGET_IMAGE】。值得注意的是打了新的TAG虽然会多了一条记录,但是从IMAGE ID 可以得知他们是同一个镜像。

执行完docker tag命令后,使用查询镜像命令查看镜像列表。可以看到,镜像列表中多了一个mybusybox的镜像。busybox和mybusybox这两个镜像的 IMAGE ID 是完全一样的。实际上它们指向了同一个镜像文件,只是别名不同而已。

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB
mybusybox           latest              018c9d7b792b        3 weeks ago         1.22MB

而形如【
registry.hepantec.com/private_repo/busybox】这样的image实际上也是可以通过打tag的方法然后直接推送到其他仓库的,示例如下:

$ docker tag registry.test.com/myrepo/busybox:1.2   registry.online.com/myrepo/busybox:1.0

$ docker images
REPOSITORY                                                 TAG       IMAGE ID             CREATED           SIZE
registry.test.com/myrepo/busybox:1.2         latest    018c9d7b792b     3 weeks ago     1.22MB
registry.online.com/myrepo/busybox:1.0     latest    018c9d7b792b      3 weeks ago    1.22MB

$ docker push  registry.online.com/myrepo/busybox:1.0

(4)删除镜像

我们可以使用docker rmi或者docker image rm命令删除镜像。

例:删除mybusybox镜像

$ docker rmi mybusybox

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

此处需要注意的是,如果这个image已经构建了容器,会删除失败。此时需要先将容器移除镜像才能删除成功。关于容器的具体使用方法将在下一篇文章中详解。

(5)构建镜像

构建镜像主要有两种方式:

  • docker commit命令从运行中的容器提交为镜像;
  • docker build命令从 Dockerfile 构建镜像。

Docker commit命令

首先介绍下如何从运行中的容器提交为镜像。我依旧使用 busybox 镜像举例,使用以下命令创建一个名为 busybox 的容器并进入 busybox 容器。

# 创建容器
$ docker run -itd busybox
# 通过docker ps可以看到刚刚创建的容器,然后进入容器
$ docker exec -it 容器id /binn/bash

执行完上面的命令后,当前窗口会启动一个 busybox 容器并且进入容器中。在容器中,执行以下命令创建一个文件并写入内容:

touch hello.txt && echo "I love Docker. " > hello.txt

此时在容器的根目录下,已经创建了一个 hello.txt 文件,并写入了 "I love Docker. "。下面,我们新打开另一个命令行窗口,运行以下命令提交镜像:

$ docker commit busybox busybox:hello
sha256:cbc6406aaef080d1dd3087d4ea1e6c6c9915ee0ee0f5dd9e0a90b03e2215e81c

然后使用上面讲到的docker image ls命令查看镜像:

$ docker image ls busybox
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             hello               cbc6406aaef0l        2 minutes ago       1.22MB
busybox             latest              018c9d7b792b        4 weeks ago         1.22MB

此时我们可以看到主机上新生成了 busybox:hello 这个镜像。

Docker build命令

最常用的镜像构建方式:Dockerfile。Dockerfile 是一个包含了用户所有构建命令的文本。通过docker build命令可以从 Dockerfile 生成镜像。

使用 Dockerfile 构建镜像具有以下特性:

  • Dockerfile 的每一行命令都会生成一个独立的镜像层,并且拥有唯一的 ID;
  • Dockerfile 的命令是完全透明的,通过查看 Dockerfile 的内容,就可以知道镜像是如何一步步构建的;
  • Dockerfile 是纯文本的,方便跟随代码一起存放在代码仓库并做版本管理。

先学习下 Dockerfile 常用的指令。

Dockerfile 指令 指令简介

  • FROM Dockerfile 除了注释第一行必须是 FROM ,FROM 后面跟镜像名称,代表我们要基于哪个基础镜像构建我们的容器。( 默认会先从本地去查找镜像
  • RUN RUN 后面跟一个具体的命令,类似于 Linux 命令行执行命令。
  • ADD 拷贝本机文件或者远程文件到镜像内
  • COPY 拷贝本机文件到镜像内
  • USER 指定容器启动的用户
  • ENTRYPOINT 容器的启动命令
  • CMD CMD 为 ENTRYPOINT 指令提供默认参数,也可以单独使用 CMD 指定容器启动参数
  • ENV 指定容器运行时的环境变量,格式为 key=value
  • ARG 定义外部变量,构建镜像时可以使用 build-arg = 的格式传递参数用于构建
  • EXPOSE 指定容器监听的端口,格式为 [port]/tcp 或者 [port]/udp
  • WORKDIR 为 Dockerfile 中跟在其后的所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 命令设置工作目录。

先分析下如下Dockerfile文件中的含义:

FROM centos:7
COPY nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum install -y nginx
EXPOSE 80
ENV HOST=mynginx
CMD ["nginx","-g","daemon off;"]
  • 第一行表示我要基于 centos:7 这个镜像来构建自定义镜像。这里需要注意,每个 Dockerfile 的第一行除了注释都必须以 FROM 开头。
  • 第二行表示拷贝本地文件 nginx.repo 文件到容器内的 /etc/yum.repos.d 目录下。这里拷贝 nginx.repo 文件是为了添加 nginx 的安装源。
  • 第三行表示在容器内运行yum install -y nginx命令,安装 nginx 服务到容器内,执行完第三行命令,容器内的 nginx 已经安装完成。
  • 第四行声明容器内业务(nginx)使用 80 端口对外提供服务。
  • 第五行定义容器启动时的环境变量 HOST=mynginx,容器启动后可以获取到环境变量 HOST 的值为 mynginx。
  • 第六行定义容器的启动命令,命令格式为 json 数组。这里设置了容器的启动命令为 nginx ,并且添加了 nginx 的启动参数 -g 'daemon off;' ,使得 nginx 以前台的方式启动。

上面这个 Dockerfile 的例子基本涵盖了常用的镜像构建指令。目录中配置好Dockerfile之后,就可以进行镜像构建了。命令形如:

$ docker build -t IMAGE_NAME ./image_dir

上面命令就是基于image_dir目录进行镜像构建的方法,Dockerfile文件就在image_dir这个目录中,如果不在就会构建失败。

限于篇幅原因关于docker镜像的探讨本篇就先到这里,后续将继续更新,敬请期待……

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...