文章目录
一、Docker 镜像(Docker Image)详解
Docker 镜像本质上是一个只读文件,包含了文件系统、源码、库文件、依赖、工具等一系列运行应用所需的文件。
可以将 Docker 镜像视为一个模板,通过它可以实例化出多个容器。
Docker 镜像采用联合文件系统(Union FS),这种文件系统将多个目录层叠在一起,形成一个虚拟的文件系统。每一层文件系统称为一层(layer)。联合文件系统允许对每一层设置三种权限:只读(readonly)、读写(readwrite)和可覆盖(whiteout-able)。不过,在 Docker 镜像中,所有的文件层都默认是只读的。
在构建镜像时,从最基本的操作系统开始,每进行一次构建操作,就会在镜像中添加一层文件系统。每一层都会覆盖底层的文件和目录,就像上层覆盖了下层的可见内容一样。当你运行容器时,看到的将是一个完整的文件系统,尽管实际上它由多层文件系统组成,你并不需要知道其中有多少层,也不会看到每层的具体修改内容。
1.1 Docker 镜像的结构
只读文件:Docker 镜像的内容是只读的,意味着一旦构建完成后,镜像中的文件无法被修改。镜像的这一特性使得镜像成为一个稳定的构建单元。
多层结构(Union FS):Docker 镜像由一层层文件系统组成,每一层都是基于上一层文件系统的修改。可以通过联合文件系统(Union FS)将这些层合并成一个虚拟的文件系统。每个层表示一次修改,Docker 会在最基础的镜像上,基于应用需求继续叠加不同的层。
1.2 Docker 镜像的每一层(Layer)
每一层文件系统都包含一些变化,比如安装软件包、修改配置文件等。这些层之间具有一定的层次关系,其中:
只读层(readonly):每个镜像的层是只读的,意味着这些文件不能被更改。任何对镜像内容的修改都会形成一个新的层,并与上层合并。
读写层(readwrite):每个容器在运行时会有一个读写层,容器的文件变动(如数据文件的创建或修改)都会保存在这个层中。这个层仅对该容器有效,不会影响镜像本身。
写出层(whiteout-able):这是指 Docker 镜像中某些文件的“遮盖”层。例如,在底层的某一层文件被删除或者覆盖,Docker 会在上层创建一个类似“遮盖”文件的层,使得底层文件对外不可见。
1.3 镜像的构建过程
在构建 Docker 镜像时,通常从一个基础的操作系统镜像(如 Ubuntu 或 Alpine)开始,逐步添加应用程序、库文件、工具、依赖和配置。每一次的构建操作都会生成一层文件系统,并与之前的层叠加,最终形成一个完整的镜像。
例如:
- 第一层:基础操作系统镜像(如 Ubuntu)。
- 第二层:安装了必要的系统依赖库。
- 第三层:安装应用程序(例如 Web 服务器)。
- 第四层:配置文件或其他特定环境设置。
每一层文件的修改只对当前层可见,而上层的文件会覆盖下层的相同路径文件,形成一种 “层叠式” 的文件系统结构。
1.4 镜像的使用
当我们使用 Docker 镜像时,我们并不需要关心它的具体层次结构,Docker 会自动处理这些层并将其合并成一个完整的文件系统供容器使用。容器从镜像创建时,会生成一个可写的层,这个层可以在容器运行过程中进行修改,但镜像本身仍然保持不变。
1.5 镜像的优势
- 高效的存储:通过层级叠加和只读的设计,Docker 镜像避免了重复存储相同的数据,不同容器可以共享相同的底层镜像数据。
- 易于版本控制:每个镜像层代表一次构建步骤,这样可以追溯到每个层的修改历史。
- 快速构建与分发:基于镜像的构建方式,可以非常快速地构建、启动和分发容器,减少了环境配置的时间成本。
二、为什么需要镜像
在软件开发中,我们常常会遇到一个问题:软件开发完毕后,如何将其交付给他人进行运行?尤其是在环境不一致的情况下,如何保证软件在不同环境中能够正确运行?
通常,开发人员会通过手动部署或者编写脚本来解决部署问题。但即使如此,本地环境与云端环境之间仍然存在一致性问题。每个用户在为应用打包时,常常需要进行繁琐的配置和修改。
Docker 镜像正是为了解决这个问题而诞生的。它通过将一个镜像制作成一个包含操作系统所有文件和目录结构的压缩包,确保其与本地及测试环境的操作系统完全一致。这样,用户就可以在不同环境中无缝地运行相同的软件。
Docker 最大的贡献之一是定义了容器镜像的分层存储格式。Docker 镜像技术基于联合文件系统(UnionFS),其文件系统采用分层设计。每一层都可以被多个容器共享,这不仅提高了存储效率,还能减少存储空间的占用。
此外,Docker 镜像提供了一种打包应用程序和预配置服务器环境的便捷方式。无论是个人使用还是与其他 Docker 用户共享,都变得更加轻松和高效。
三、镜像命令
3.1 命令清单
命令 | 别名 | 功能 | 备注 |
---|---|---|---|
docker images |
docker image ls |
列出本地镜像 | 必须掌握 |
docker tag |
docker image tag |
给镜像打标签,可用于推送镜像仓库 | 必须掌握 |
docker pull |
docker image pull |
从镜像仓库拉取镜像 | 和镜像仓库命令相同,也可以归类为镜像操作命令,必须掌握 |
docker push |
docker image push |
推送镜像到仓库 | 和镜像仓库命令相同,也可以归类为镜像操作命令,必须掌握 |
docker rmi |
docker image rm |
删除本地镜像 | 必须掌握 |
docker build |
docker image build |
通过 Dockerfile 制作镜像 | 必须掌握 |
docker save |
docker image save |
将指定镜像保存成 tar 归档文件 | 必须掌握 |
docker load |
docker image load |
导入使用 docker save 命令导出的镜像 |
必须掌握 |
docker inspect |
docker image inspect |
查看镜像详细信息 | 必须掌握 |
docker history |
docker image history |
查看镜像历史 | 必须掌握 |
docker import |
docker image import |
从归档文件创建镜像 | |
docker export |
从容器导出文件创建镜像 | ||
docker image prune |
删除不使用的镜像 |
3.2 详细解释
docker images
- 功能:
列出本地镜像。 - 语法:
docker images [OPTIONS] [REPOSITORY[:TAG]]
- 别名:
docker image ls, docker image list
- 关键参数:
-a
:列出本地所有的镜像(包括中间镜像层,默认过滤掉中间镜像层)。--digests
:显示镜像的摘要信息。-f
:显示满足条件的镜像。--format
:指定返回值的模板文件。--no-trunc
:显示完整的镜像信息。-q
:只显示镜像 ID。
- 样例:
# 列出本地全部镜像 docker images # 列出本地镜像中 REPOSITORY 为 ubuntu 的镜像列表 docker images ubuntu
- 功能:
docker tag
- 功能:
标记本地镜像,将其归入某一仓库。 - 语法:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
- 别名:
docker image tag
- 样例:
docker tag ubuntu:22.04 myregistry.com/myubuntu:22.04
- 功能:
docker pull
- 功能:
拉取镜像。 - 参考命令:
使用docker pull
拉取镜像。
- 功能:
docker push
- 功能:
推送镜像到远程仓库。 - 参考命令:
使用docker push
推送镜像。
- 功能:
docker rmi
- 功能:
删除镜像。 - 语法:
docker rmi [OPTIONS] IMAGE [IMAGE...]
- 别名:
docker image rm, docker image remove
- 关键参数:
-f
:强制删除。--no-prune
:不移除该镜像的中间镜像层,默认会移除。
- 样例:
docker rmi maxhou/mybusybox:v0.1
- 功能:
docker save
- 功能:
将指定镜像保存成 tar 归档文件。 - 语法:
docker save [OPTIONS] IMAGE [IMAGE...]
- 别名:
docker image save
- 关键参数:
-o
:指定输出到的文件。
- 样例:
docker save -o mynginx_1.22.1.tar nginx:1.22.1
- 功能:
docker load
- 功能:
导入使用docker save
命令导出的镜像。 - 语法:
docker load [OPTIONS]
- 别名:
docker image load
- 关键参数:
--input, -i
:指定导入的文件,代替 STDIN。--quiet, -q
:精简输出信息。
- 样例:
docker load -i mynginx_1.22.1.tar
- 功能:
docker image inspect
- 功能:
查看镜像详细信息。 - 语法:
docker image inspect [OPTIONS] IMAGE [IMAGE...]
- 样例:
docker image inspect nginx:1.23.3
- 功能:
docker history
- 功能:
显示镜像历史。 - 语法:
docker history [OPTIONS] IMAGE
- 别名:
docker image history
- 关键参数:
-H, --human
:使用人类可读的格式显示大小和日期。--no-trunc
:显示完整信息,不做截断。-q, --quiet
:只显示镜像 ID 信息。
- 样例:
docker history nginx:1.21.1
- 功能:
docker import
- 功能:
从归档文件中创建镜像。 - 语法:
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
- 别名:
docker image import
- 关键参数:
-c
:应用 Docker 指令创建镜像。-m
:提交时的说明文字。
- 样例:
docker import my_ubuntu_v3.tar maxhou/ubuntu:v4
- 功能:
docker image prune
- 功能:
删除不使用的镜像。 - 语法:
docker image prune [OPTIONS]
- 关键参数:
-a, --all
:删除全部不使用的镜像。--filter filter
:指定过滤条件。-f, --force
:不提示是否删除。
- 样例:
docker image prune
- 功能:
docker build
- 功能:
使用 Dockerfile 创建镜像。 - 语法:
docker build [OPTIONS] PATH | URL | -
- 关键参数:
--build-arg=[]
:设置镜像创建时的变量。-f
:指定要使用的 Dockerfile 路径。--label=[]
:设置镜像使用的元数据。--no-cache
:创建镜像时不使用缓存。--pull
:尝试更新镜像的新版本。--quiet, -q
:安静模式,仅输出镜像 ID。--rm
:设置镜像成功后删除中间容器。--tag, -t
:设置镜像的名称和标签。--network
:设置构建时的 网络模式。
- 样例:
docker build -t mynginx:v1 .
- 功能:
四、docker 操作案例
4.1 查找镜像
通过 docker search <镜像名>
可以进行查找镜像:
ubuntu@VM-8-2-ubuntu:~$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 16750 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker... 2259
bitnami/nginx Bitnami NGINX Docker Image 458 [OK]
nginxinc/nginx-unprivileged Unprivileged NGINX Docker Image 102
tiangolo/nginx-rtmp NGINX with RTMP module 310
...
4.2 下载镜像
通过 docker pull <镜像名>
可以进行镜像的下载:
ubuntu@VM-8-2-ubuntu:~$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete
Digest: sha256:7e1a4e2d11e2ac7a8c3f768d4166c2defeb09d2a750b010412b6ea13de1efb19
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
4.3 查看镜像与列表存储位置
通过 docker images <镜像名>
进行查看。
ubuntu@VM-8-2-ubuntu:~$ docker images busybox
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest af4709625109 5 months ago 4.27MB
4.4 查询镜像详情
通过 docker inspect <镜像名称或ID>
查询镜像详情:
ubuntu@VM-8-2-ubuntu:~$ docker inspect nginx:1.24.0
[
{
"Id": "sha256:6c0218f1687660914d2ce279489e9b6d62a5a48d06ab2e27b7710c19d5e904e5",
"RepoTags": [
"nginx:1.24.0"
],
"RepoDigests": [
"nginx@sha256:f6daac2445b0ce70e64d77442ccf62839f3f1b4c24bf6746a857eff014e798c8"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2023-04-11T19:57:20Z",
"DockerVersion": "",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.24.0",
"NJS_VERSION=0.7.12",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"ArgsEscaped": true,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 142307645,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/72a01f43b6cbd622a7a36cc56a370dbd422c4ef2d7e648bd4b3530ad397019d0/diff:/var/lib/docker/overlay2/14f76e39f3d3db99bb560986456e945e96e6371e9eee8d4765ddf714bcc310f9/diff:/var/lib/docker/overlay2/a8657c730fdf1b491a0805f4350c5a7ca425735ece429004c520dcbd8e3c22a0/diff:/var/lib/docker/overlay2/d49d03c9a1f000158620491d3bcc6d7973a294985021ae00680bc7054cbf71cb/diff:/var/lib/docker/overlay2/e999764fb57e3b6f2420033145ac645a808a161a7463ad9ce22d0d82698e394e/diff",
"MergedDir": "/var/lib/docker/overlay2/34d07e4038035e87adb60f70795a66fb373a65e1fae27bde363f216c0e5b347a/merged",
"UpperDir": "/var/lib/docker/overlay2/34d07e4038035e87adb60f70795a66fb373a65e1fae27bde363f216c0e5b347a/diff",
"WorkDir": "/var/lib/docker/overlay2/34d07e4038035e87adb60f70795a66fb373a65e1fae27bde363f216c0e5b347a/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:420179ad2efafbf953a0c75f68a4c9dfaf38a98643df97d415bce49b179895f7",
"sha256:13c8460bfc9a101c9d6fe94fc9c71f56a95fe69124ca0f51f08dc2b0dbd5956c",
"sha256:b9a187a24e195526ec928d77020241c6965abc70102d604fd424d7d7a3caf796",
"sha256:96c08fed6a4cb59eeeb7c0bd67f71a17e0e8981e29903dc589c07cfee160c815",
"sha256:29492f82bbc2d3446f771f4db2cf5afba6c73c40a834c2a74b27e461721b0870",
"sha256:bc4a3582faa9d8347cf764790d3a90c117d4c8a308f48e5716476380882d49ab"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
4.5 查看镜像分层
通过 docker history <镜像名>
可以查看镜像分层。
docker image inspect <镜像名>
可以查看详细的分层
ubuntu@VM-8-2-ubuntu:~$ docker history nginx:1.24.0
IMAGE CREATED CREATED BY SIZE COMMENT
6c0218f16876 23 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
<missing> 23 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
<missing> 23 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 23 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
<missing> 23 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB buildkit.dockerfile.v0
<missing> 23 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.27kB buildkit.dockerfile.v0
<missing> 23 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 2.12kB buildkit.dockerfile.v0
<missing> 23 months ago COPY docker-entrypoint.sh / # buildkit 1.62kB buildkit.dockerfile.v0
<missing> 23 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.7MB buildkit.dockerfile.v0
<missing> 23 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
<missing> 23 months ago ENV NJS_VERSION=0.7.12 0B buildkit.dockerfile.v0
<missing> 23 months ago ENV NGINX_VERSION=1.24.0 0B buildkit.dockerfile.v0
<missing> 23 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
<missing> 23 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 23 months ago /bin/sh -c #(nop) ADD file:5d6b639e8b6bcc011… 80.6MB
4.6 打标签
通过 docker tag <源镜像> <目标镜像>
命令;
docker tag nginx:latest nginx:v1
4.7 推送镜像
在推送镜像前首先要进行登录,即 docker login
进行登录,随后通过 docker push <镜像名>
进行推送即可
4.8 运行容器
通过 docker run [选项] <镜像名称> [命令]
进行运行容器,常用选项:
-d
:后台运行容器。-p
:将容器的端口映射到宿主机的端口。--name
:给容器指定一个名称。-e
:设置环境变量。--rm
:容器停止后自动删除容器。-v
:挂载卷或目录。-it
:交互式运行容器,通常与终端一起使用。
docker run -d nginx
五、Docker 镜像伴随什么使用?
Docker 镜像一般与以下几个组件和工具一起使用,可以先进行简要了解,之后再对这些组件/工具进行学习:
1. Docker 容器
Docker 镜像是容器化应用的蓝图,而容器是运行这些镜像的实例。镜像包含了运行应用所需的所有依赖、环境和配置。当你运行一个容器时,Docker 会根据镜像来创建该容器。
- 镜像:是只读的、不可修改的文件系统,包含了操作系统、应用程序以及相关依赖。
- 容器:是镜像的一个运行实例,它是隔离的、可读写的环境,能进行操作和处理数据。
例如:docker run -d my-image
会使用 my-image
镜像启动一个容器。
2. Dockerfile
Dockerfile 是用于构建 Docker 镜像的脚本,它定义了镜像的内容,包括操作系统的选择、应用程序安装、配置文件的添加等。通过运行 docker build
命令,你可以从 Dockerfile 创建自定义镜像。
例如,docker build -t my-app .
使用 Dockerfile 构建 my-app
镜像。
3. Docker Hub 或 私有 Docker 仓库
Docker Hub 是一个公共的 Docker 镜像库,用户可以从中下载现成的镜像,或将自己的镜像推送到该平台进行分享和管理。企业或个人也可以使用私有仓库来管理和存储镜像,例如:
- Docker Hub:用于公共或私有镜像存储和分发。
- 私有 Docker 仓库:例如 Docker Registry,适用于公司或组织内部使用。
例如:docker pull nginx
从 Docker Hub 拉取 Nginx 镜像。
4. Docker Compose
Docker Compose 是一个工具,用于定义和管理多容器应用。通过 docker-compose.yml
文件,用户可以定义多个容器及其网络、卷、环境变量等配置。Docker Compose 使得管理由多个容器组成的应用变得简单。
例如:
version: '3'
services:
web:
image: nginx
ports:
- "80:80"
db:
image: postgres
使用 docker-compose up
启动多个容器。
5. Docker 网络
Docker 网络用于容器之间的通信。通过网络,容器可以相互访问,也可以与外部世界交互。默认情况下,Docker 会创建多个网络选项,如 bridge
、host
和 none
。用户可以创建自定义网络来实现不同的隔离和通信需求。
例如:使用 docker network create
创建一个自定义网络,并通过 docker run
将容器连接到该网络。
6. Docker 卷(Volumes)
Docker 卷用于容器的数据持久化。容器本身是临时的,当容器删除时,其内的数据也会丢失。通过使用卷,数据可以保存在容器外部,即使容器重启或删除,数据依然存在。
例如:
docker run -v /my/host/data:/container/data my-image
7. CI/CD 工具
在自动化构建和部署中,Docker 镜像通常与 CI/CD 工具(如 Jenkins、GitLab CI、Travis CI)配合使用。通过这些工具,你可以自动构建镜像、运行容器、测试和部署应用。
8. Kubernetes 或 Docker Swarm
当应用需要在多个机器上进行分布式部署时,Docker 镜像常与容器编排工具(如 Kubernetes 或 Docker Swarm)一起使用。这些工具管理多个容器的部署、扩展和高可用性。
例如:
- Kubernetes:通过配置文件(如 YAML)管理多个 Docker 容器的生命周期、网络、存储等。
- Docker Swarm:是 Docker 提供的容器编排工具,帮助管理多个 Docker 容器的部署和扩展。
简要总结:
Docker 镜像通常与容器、Dockerfile、Docker Hub、Docker Compose、网络、卷、CI/CD 工具和容器编排工具(如 Kubernetes 或 Docker Swarm)一同使用。它们共同构成了容器化应用的基础设施,帮助开发、测试、部署和管理容器化应用。
六、综合练习
6.1 离线迁移镜像
离线迁移 Docker 镜像,即将一个镜像从一个机器导出到另一个机器,而不是通过网络推送到远程仓库。这个过程包括将镜像保存为 tar 文件、传输文件、然后在目标机器上加载镜像。
步骤:
- 在源机器上保存 Docker 镜像
首先,使用 docker save
命令将 Docker 镜像保存为一个 tar 文件。
比如我们要迁移的镜像是 myapp:latest
,可以执行以下命令:
docker save -o myapp_latest.tar myapp:latest
- 将 tar 文件传输到目标机器
将保存的 tar 文件传输到目标机器。可以使用 SCP、FTP、USB等方式来传输文件。
这里我们使用 SCP 将文件传输到目标机器的 /tmp
目录:
scp myapp_latest.tar user@target-machine:/tmp/
- 在目标机器上加载 Docker 镜像
当文件传输到目标机器上,就可以使用 docker load
命令来加载该镜像。
在目标机器上执行以下命令:
docker load -i /tmp/myapp_latest.tar
执行后有如下输出:
$ docker load -i /tmp/myapp_latest.tar
Loaded image: myapp:latest
- 验证镜像是否已加载成功
加载镜像后,可以使用 docker images
命令来查看是否镜像已经存在:
输出:
REPOSITORY TAG IMAGE ID CREATED SIZE
myapp latest d3b07384d113 2 hours ago 1.23GB
此时镜像 myapp:latest
已经成功加载到目标机器。
- 在目标机器上运行镜像
如果镜像加载成功,则可以在目标机器上运行该镜像:
docker run -d --name myapp_container myapp:latest
简单总结就是:
源机器:
docker save -o myapp_latest.tar myapp:latest
保存镜像。- 使用
scp
等方式传输 tar 文件到目标机器。
目标机器:
docker load -i /tmp/myapp_latest.tar
加载镜像。- 使用
docker images
验证镜像是否成功加载。 - 使用
docker run
启动容器。
6.2 镜像存储的压缩与共享
- 拉取 Nginx 镜像
首先,拉取 nginx:1.21.1
镜像。如果本地没有该镜像,Docker 会从仓库拉取;如果镜像已存在,系统会提示镜像已更新为最新版本。
docker pull nginx:1.21.1
执行结果:
1.21.1: Pulling from library/nginx
Digest: sha256:f92ab9bdf24c9fbbacbd7d342e3fa27c22ad98d7c8aebfa25b78173901a4269b
Status: Image is up to date for nginx:1.21.1
docker.io/library/nginx:1.21.1
- 查看本地镜像
使用docker images
命令查看本地镜像,可以看到nginx:1.21.1
镜像的大小为 144MB。
docker images
执行结果:
REPOSITORY TAG IMAGE ID CREATED SIZE
ccr.ccs.tencentyun.com/maxhou/mybusybox v0.3 cd8e1c62f75f 5 days ago 5.23MB
busybox latest cd8e1c62f75f 5 days ago 5.23MB
maxhou/mybusybox v0.2 cd8e1c62f75f 5 days ago 5.23MB
nginx 1.23.4 9a3a5ab13d28 10 days ago 144MB
nginx 1.21.1 274bd4c58d91 15 months ago 136MB
镜像压缩情况
我们注意到nginx:1.21.1
镜像的大小为 140MB 多,但在 Docker Hub 上查看时,镜像的大小大约为 50MB,这意味着镜像在传输时已经进行了压缩。仓库到本地的镜像文件越小越好,以减少网络带宽的消耗。给镜像打多个 Tag 并推送到仓库
接下来,我们给nginx:1.23.4
镜像打多个标签,并同时推送到 Docker 仓库。在推送过程中,如果镜像层已经存在,Docker 会提示“层已经存在”,不会重复存储。
docker tag nginx:1.23.4 maxhou/mybitnginx:1.23.4
docker tag nginx:1.23.4 maxhou/mybitnginx:1.23.5
docker tag nginx:1.23.4 maxhou/mybitnginx:1.23.6
docker tag nginx:1.23.4 maxhou/mybitnginx:1.23.7
docker push maxhou/mybitnginx:1.23.4
docker push maxhou/mybitnginx:1.23.5
docker push maxhou/mybitnginx:1.23.6
docker push maxhou/mybitnginx:1.23.7
执行结果:
The push refers to repository [docker.io/maxhou/mybitnginx]
9a3a5ab13d28: Layer already exists
6c4e23d5949f: Layer already exists
f8c44d2f7a6b: Layer already exists
db1a589f29b7: Layer already exists
73f1b8f087da: Layer already exists
bfb2893ab10a: Layer already exists
1.23.4: digest: sha256:afa5432195b25d57dbcf02a4132fa47ac85f95f45d7b4096592f12bcd99bdaef
1.23.5: digest: sha256:afa5432195b25d57dbcf02a4132fa47ac85f95f45d7b4096592f12bcd99bdaef
1.23.6: digest: sha256:afa5432195b25d57dbcf02a4132fa47ac85f95f45d7b4096592f12bcd99bdaef
1.23.7: digest: sha256:afa5432195b25d57dbcf02a4132fa47ac85f95f45d7b4096592f12bcd99bdaef
在推送过程中,Docker 提示已存在的镜像层不会被重复上传,而是直接使用已有的层。
- 推送新镜像并发现已存在的层
如果 Docker Hub 中已经存在某些镜像层,Docker 会检测到并使用挂载的方式(mounted
),而不会将这些层重新推送到仓库。
docker tag nginx:1.18.0 maxhou/mybitnginx:1.18.0
docker push maxhou/mybitnginx:1.18.0
执行结果:
The push refers to repository [docker.io/maxhou/mybitnginx]
a1b16b2fefcd: Mounted from library/nginx
af6c64853123: Mounted from library/nginx
f37cd3bb1cc5: Mounted from library/nginx
1.18.0: digest: sha256:7a71fc31ab0e4ea52877bfb10ffcd9b05a1cc9e0b7727d238e98c7972aefedb6
解释:
- 在推送
nginx:1.18.0
镜像时,Docker Hub 发现该镜像的层已经存在,因此使用了挂载的方式(Mounted from library/nginx
),没有重复上传这些镜像层。
<font face=幼圆" color=#cc0033 size=4>总结
- 拉取镜像:通过
docker pull
拉取nginx:1.21.1
镜像。 - 查看镜像大小:通过
docker images
查看本地镜像,发现镜像压缩。 - 推送多个标签:为一个镜像打多个标签,并推送到 Docker Hub,注意层的复用。
- 层复用:如果镜像层已存在,Docker 会挂载这些层而不是重复上传。