文章目录
一、什么是docker镜像
二、为什么需要镜像
三、镜像相关命令详解
3、1 命令清单
3、2 命令详解
四、镜像实战
4、1 镜像操作案例
4、2 离线迁移镜像
4、3 镜像存储的压缩与共享
🙋♂️ 作者:@Ggggggtm 🙋♂️
👀 专栏:Docker 👀
💥 标题:docker镜像 💥
❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️
一、什么是docker镜像
我们一直说docker镜像,那么docker镜像到底是什么呢?
- Docker image 本质上是一个 read-only 只读文件, 这个文件包含了文件系统、源码、库文件、依赖、工具等一些运行 application 所必须的文件。
- 我们可以把 Docker image 理解成一个模板, 可以通过这个模板实例化出来很多容器。
- image 里面是一层层文件系统 Union FS。联合文件系统,可以将几层目录挂载到一起,形成一个虚拟文件系统。
- 每一层文件系统我们叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)和写出(whiteout-able),但是 docker镜像中每一层文件系统都是只读的。
构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统。一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样。当你使用的时候,你只会看到一个完全的整体,你不知道里面有几层,也不清楚每一层所做的修改是什么。
通俗理解,Docker镜像是用于创建和运行容器的轻量级、可执行的独立软件包。它是一个包含了应用程序的文件系统,其中包括了运行该应用程序所需的所有内容:代码、运行时环境、系统工具、系统库以及依赖的软件。镜像是用于创建容器的模板,并且可以被共享和重复使用。
二、为什么需要镜像
在部署应用时,通过手工或写一些脚本的方式进行部署。这样部署面临问题就是云端和本地环境一致问题。用户为每个应用打包过程比较繁琐,需要配置和给中修改等操作,非常费劲。
然而, Docker 镜像就是为了解决这个小小的打包功能,突然一夜之间成名。那么,你可能说 Docker 镜像就是个压缩包,是的,你猜对了,它就像一个压缩包文件。它是如何解决 Paas 时代所面临的云端和本地一致性问题?很简单,它是把一个镜像制作成一个完整的操作系统所有文件和对应的目录结构,这样的压缩包是跟你本地和测试环境用的操作系统一摸一样。
docker 最大的贡献就是定义了容器镜像的分层的存储格式, docker 镜像技术的基础是联合文件系统(UnionFS),其文件系统是分层的。这样既可以充分利用共享层,又可以减少存储空间占用。
docker 镜像提供了一种打包应用程序和预配置服务器环境的便捷方式,可以很方便的将其用于个人用途或与其他 Docker 用户公开共享。
ps:通常在虚拟机中的 OS 基本上都是以G为单位的,为什么在 Docker 镜像中才100M左右?
其实是因为,对于一个精简版的操作系统,rootfs 可以非常小,只需要包含基本的命令、工具和程序库即可,因为底层直接使用宿主机的 kernel,自己只需要提供 rootfs 便可。此外,即使存在不同的 Linux 发行版本,但是 bootfs 基本都是一致的,可以公用 bootfs。
三、镜像相关命令详解
3、1 命令清单
docker镜像命令清单及简单解释:
3、2 命令详解
有一部分命令是在前面的文章中有详解,所以在这里就简单解释。新的一些命令会详细解释,并且解释实际举例子!
docker images:查看本地镜像
我们知道当我们从docker远端仓库拉取镜像后,都过存储到我们本地的主机上。可以通过docker images 来查看本地主机上的镜像都有哪些。如下图:
docker images还有一些常用的选项:
- -a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
- --digests :显示镜像的摘要信息;
- -f :显示满足条件的镜像;
- --format :指定返回值的模板文件;
- --no-trunc :显示完整的镜像信息;
- -q :只显示镜像 ID。
一些常用选项举例如下图:
docker tag :给镜像打标签
在Docker中,docker tag命令用于为一个已存在的镜像创建一个新的标签。它可以为镜像指定一个更友好或更具描述性的名称,也可以用于创建镜像的不同版本。以下是docker tag命令的详细解释:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
我们再来结合之前的例子来理解一下,如下图:
简单理解,docker tag就是给镜像重命名,但是不仅仅是对镜像名称重命名,还可以对其tag标签重命名。一般docker tag都是与docker push一起用,也就是对镜像创建一个新的标签后,可以推送到远端仓库。
docker pull、docker push参看上一篇文章!
docker rmi:删除镜像
本地镜像可是需要占用磁盘空间的。当我们不再使用该镜像时,可以直接将镜像删除。它还有一些常用选项:
- -f :强制删除;
- --no-prune :不移除该镜像的过程镜像,默认移除;
先查看一下本地镜像,如下图:
我们现在想要删除Ubuntu镜像。具体如下图:
通过上图我们发现,该镜像被一个容器正在使用。我们通过docker ps -a来查看一下。如下图:
我们发现该容器已经停止运行了,所以可以通过docker rm 将该容器进行删除。如下图:
但是我们删除该容器后,发现依旧删除不了该镜像,是因为任然有容器在使用该镜像。我们再次对容器进行删除。直到没有容器使用该镜像时,就可以删除该镜像了。但是我们发现删除容器也是很麻烦的一个过程,同时我们又确定了该镜像不再使用,就可以加上-f选项,就是强制删除!如下图:
docker save:将指定镜像保存成 tar 归档文件
docker save是用于将Docker镜像保存成本地文件的命令。它将指定的镜像及其所有依赖的层和元数据打包成一个.tar文件。这个文件可以在离线环境或其他Docker主机上传输,并通过docker load命令重新加载为可用的镜像。
使用docker save命令需要提供镜像的名称或ID,并可以选择指定输出文件的路径和文件名。例如,以下是docker save命令的基本语法:
docker save [OPTIONS] IMAGE [IMAGE...]
有一个常用的关键选项:-o :输出到的文件。下面我们来结合一个例子来理解一下。
先查看一下本地镜像,如下图:
现在我们想要把所有的nginx镜像打包一下,如下图:
我们也能看到形成了一个mynginx.tar的文件。下面我们结合docker load命令再次理解docker save。
docker load:导入使用docker save命令导出的镜像
docker load命令用于从本地文件加载Docker镜像。它可以将通过docker save命令保存的镜像文件重新加载为可用的镜像,并添加到本地的Docker镜像库中。
使用docker load命令需要提供从docker save命令获取的.tar文件的路径。以下是docker load命令的基本语法:
docker load [OPTIONS]
关键参数
- --input , -i : 指定导入的文件,代替 STDIN。
- --quiet , -q : 精简输出信息。
我们在讲解docker save时,已经形成了自己的nginx的tar包。我们先来查看一下本地镜像。如下:
为了更加突出实验现象,我们可以先把nginx的镜像进行删除。然后在加载我们的tar包。如下图:
我们再次加载一下我们刚刚形成的tar包。如下图:
可以看到我们删除的镜像,通过加载tar包后再次出现了。
docker image inspect:查看镜像详细信息。参考上篇文章。
docker history:显示镜像历史
docker history命令是Docker提供的一个用于查看镜像创建历史的工具。它显示了构建一个镜像所用到的各个层次以及每个层次对应的命令。
使用docker history命令的语法如下:
docker history [OPTIONS] IMAGE
一些关键参数如下:
- -H , --human :大小和日期采用人容易读的格式展现
- --no-trunc :显示全部信息,不要隔断;
- -q, --quiet: 只显示镜像 id 信息;
下面我们看一个实际例子:
默认情况下就是带着 -H 选项的,其意思就是把SIZE变成带有单位的,而不是字节。
docker import 和 docker build会在后续文章中详细解释。
docker image prune:删除不使用的镜像
docker image prune 是用于清理未使用的 Docker 镜像。当你在使用 Docker 运行容器时,可能会生成许多不再需要的镜像,这些镜像占据了硬盘空间。docker image prune 命令可以帮助你清理这些不再使用的镜像,释放出宝贵的存储空间。
当你执行 docker image prune 命令时,Docker 会自动检查你的系统,找到那些没有被任何容器所使用的镜像,并将其标记为"未使用"。然后,你将被提示确认是否删除这些未使用的镜像。如果你确认删除,Docker 将会删除这些镜像文件,并从你的硬盘上释放空间。
执行 docker image prune 命令时,你可以使用一些额外的参数来定制清理过程。例如,你可以使用 -a 参数清理所有未使用的镜像,包括那些被没有处于运行状态的容器所引用的镜像。使用 --filter 参数可以根据特定的条件过滤要清理的镜像。使用-f参数可以跳过确认步骤,直接删除所有未使用的镜像。
需要注意的是,执行 docker image prune 命令会永久删除你的镜像文件,一旦删除将无法恢复。因此,在执行此命令之前,请务必确认你不再需要这些镜像,并且备份重要的镜像文件。
- -a , --all : 删除全部不使用的镜像;
- --filter filter:指定过滤条件;
- -f, --force :不提示是否删除;
我们先来看一如下实例:
通过上图我们看到,正常情况下还会进行提示,加上-f选项就不会再提示了。如下图:
我们再来看一下-a选项,如下图:
四、镜像实战
4、1 镜像操作案例
首先我们查找一下想要拉取的镜像,如下图:
但是我们发现有很多不想要的结果,可以通过加上一些选项来筛选一下,如下图:
当你运行docker search -f stars=10 --limit 3 busybox命令时,它会搜索Docker Hub上与busybox相关的镜像。下面是对该命令的详细解释:
- docker search: 这是Docker命令行工具提供的一个命令,用于在Docker Hub上搜索镜像。
- -f stars=10: 这是搜索选项之一,用于指定筛选条件。在这里,我们使用 stars=10来筛选出启动数为10的镜像。"stars"指的是在Docker Hub上该镜像所拥有的星标数量。
- --limit 3: 这是另一个搜索选项,用于限制结果的数量。在这里,我们指定只返回前三个匹配的镜像。
- busybox: 这是我们要搜索的关键词,代表了一个非常轻量级的Linux发行版镜像。
当我们找到有相关的镜像后,就可以进行拉取下载了。具体如下图:
当我们下载完成后,先来查看一下镜像仓库在本地的存储信息。默认的路径是:/var/lib/docker/。但是我这里修改过,但是存储信息都是一样的。具体如下图:
然后再次查看 overlay2/repositories.json 文件,该文件记录已拉取镜像文件的信息。如下图:通过查看本地镜像, 发现和 repositories.json 文件记录的信息是相同的。知道镜像在本地的存储信息后,我们还可以查看镜像的分层和一些详细信息。如下:
现在我们想要把本地的nginx镜像推送到远端的仓库中。如下图:
我们需要先对镜像打标签。所谓的打标签,也就是相当于重命名。目的是为了更好的找到我们的远端仓库。具体操作如下:
现在我们就可以直接将打过标签的镜像推送到远端镜像了。需要注意的是,推送镜像需要先登录相关的账号。如下图:
然后可以运行相关镜像,如下图:
最后我们可以删除镜像。可以根据 id 和名字删除,对于使用的镜像需要先清理容器再删除镜像。如下图:
当我们在删除有标签的镜像时,默认都是先去标签,并不是真正的删除了镜像。当只剩下最后一个标签时,才会真正的删除该镜像。具体如下图:
4、2 离线迁移镜像
首先,我们需要将服务器 1 上镜像保存为 tar 文件,如操作系统为 ubuntu。具体如下图:
然后可以通过scp命令 或者只用使用可视化工具拷贝镜像到第二台服务器上。由于这里没有第二台服务器,就不再演示。命令是
scp mytest.tar root@IP:/root/data,
每个参数的作用如下解释:
scp
: 是一个用于安全地在网络上进行文件复制的命令。它使用SSH协议来保证传输的安全性。
mytest.tar
: 这是要复制的文件的名称。在这个例子中,它是名为"mytest.tar"的文件。确保该文件位于当前工作目录下,或者你可以提供完整的文件路径。
root@IP:/root/data
: 这是远程服务器的地址和目标位置。
root
:是远程服务器的用户名。如果你与远程服务器使用不同的用户名,请相应地更改该值。IP
:是远程服务器的IP地址。确保将其替换为实际的IP地址。:/root/data
:这是远程服务器上的目标目录。在这个例子中,它是/root/data
目录。此命令将会把本地的"mytest.tar"文件复制到远程服务器上的
/root/data
目录中。请确保你具有对远程服务器的访问权限,并且输入正确的用户名和IP地址。
当tar包拷贝到第二台服务器上后,就可以将其镜像从tar包中恢复出来。然后再次运行该镜像也是可以的。即便是两台服务器的配置不相同,也是可以的。
4、3 镜像存储的压缩与共享
拉取 nginx 镜像,如果本地没有,镜像是从仓库拉取,如果有会提示镜像已经存在,并且是最新的。
Docker images 查看本地镜像,可以看到该镜像为 142Mb。
从上面看到 nginx 为 1.21.1 的大小是 140 多 MB,但是我们从 docker hub 上查看可以看到镜像是 50 多 MB,说明发生了压缩,因为仓库到本地需要走网络,所以文件越小越好。这也就意味着在拉取到本地后,也会对其进行解压。
在Docker中,digest是一个唯一标识符,用于表示镜像的内容的哈希值。它由SHA256算法生成,并且可以用来确定镜像文件的一致性和完整性,以及作为镜像的唯一标识。
当你下载或推送一个镜像时,容器运行时会使用digest来验证该镜像的完整性,以确保它与远程仓库上的镜像一致。如果digest匹配,则说明镜像未被更改;如果不匹配,则可能意味着镜像已经被篡改或损坏。
Docker使用digest的好处是,无论镜像标签如何变化(因为标签可以重新指向不同的镜像),digest都是唯一的,因此可以确保使用特定的digest始终获取相同的镜像。
你可以使用
docker image inspect <image>
命令来查看镜像的digest信息。在返回的JSON输出中,你可以找到RepoDigests
字段,其中包含了该镜像的digest值。
把一个镜像打多个 tag,然后同时推送仓库,可以看到是说层已经存在,不会重复存储。
添加一个新的镜像到我们的仓库的时候,如果 docker hub 发现已经有了是 mount的,不是从本地推上去的。