当前位置: 首页 > news >正文

【Docker基础】全面解析 Docker 镜像:构建、使用与管理

文章目录

  • 一、Docker 镜像(Docker Image)详解
    • 1.1 Docker 镜像的结构
    • 1.2 Docker 镜像的每一层(Layer)
    • 1.3 镜像的构建过程
    • 1.4 镜像的使用
    • 1.5 镜像的优势
  • 二、为什么需要镜像
  • 三、镜像命令
    • 3.1 命令清单
    • 3.2 详细解释
  • 四、docker 操作案例
    • 4.1 查找镜像
    • 4.2 下载镜像
    • 4.3 查看镜像与列表存储位置
    • 4.4 查询镜像详情
    • 4.5 查看镜像分层
    • 4.6 打标签
    • 4.7 推送镜像
    • 4.8 运行容器
  • 五、Docker 镜像伴随什么使用?
  • 六、综合练习
    • 6.1 离线迁移镜像
    • 6.2 镜像存储的压缩与共享


一、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 imagesdocker image ls列出本地镜像必须掌握
docker tagdocker image tag给镜像打标签,可用于推送镜像仓库必须掌握
docker pulldocker image pull从镜像仓库拉取镜像和镜像仓库命令相同,也可以归类为镜像操作命令,必须掌握
docker pushdocker image push推送镜像到仓库和镜像仓库命令相同,也可以归类为镜像操作命令,必须掌握
docker rmidocker image rm删除本地镜像必须掌握
docker builddocker image build通过 Dockerfile 制作镜像必须掌握
docker savedocker image save将指定镜像保存成 tar 归档文件必须掌握
docker loaddocker image load导入使用 docker save 命令导出的镜像必须掌握
docker inspectdocker image inspect查看镜像详细信息必须掌握
docker historydocker image history查看镜像历史必须掌握
docker importdocker image import从归档文件创建镜像
docker export从容器导出文件创建镜像
docker image prune删除不使用的镜像

3.2 详细解释

  1. 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
      
  2. docker tag

    • 功能
      标记本地镜像,将其归入某一仓库。
    • 语法
      docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
      
    • 别名
      docker image tag
      
    • 样例
      docker tag ubuntu:22.04 myregistry.com/myubuntu:22.04
      
  3. docker pull

    • 功能
      拉取镜像。
    • 参考命令
      使用 docker pull 拉取镜像。
  4. docker push

    • 功能
      推送镜像到远程仓库。
    • 参考命令
      使用 docker push 推送镜像。
  5. docker rmi

    • 功能
      删除镜像。
    • 语法
      docker rmi [OPTIONS] IMAGE [IMAGE...]
      
    • 别名
      docker image rm, docker image remove
      
    • 关键参数
      • -f:强制删除。
      • --no-prune:不移除该镜像的中间镜像层,默认会移除。
    • 样例
      docker rmi maxhou/mybusybox:v0.1
      
  6. docker save

    • 功能
      将指定镜像保存成 tar 归档文件。
    • 语法
      docker save [OPTIONS] IMAGE [IMAGE...]
      
    • 别名
      docker image save
      
    • 关键参数
      • -o:指定输出到的文件。
    • 样例
      docker save -o mynginx_1.22.1.tar nginx:1.22.1
      
  7. docker load

    • 功能
      导入使用 docker save 命令导出的镜像。
    • 语法
      docker load [OPTIONS]
      
    • 别名
      docker image load
      
    • 关键参数
      • --input, -i:指定导入的文件,代替 STDIN。
      • --quiet, -q:精简输出信息。
    • 样例
      docker load -i mynginx_1.22.1.tar
      
  8. docker image inspect

    • 功能
      查看镜像详细信息。
    • 语法
      docker image inspect [OPTIONS] IMAGE [IMAGE...]
      
    • 样例
      docker image inspect nginx:1.23.3
      
  9. docker history

    • 功能
      显示镜像历史。
    • 语法
      docker history [OPTIONS] IMAGE
      
    • 别名
      docker image history
      
    • 关键参数
      • -H, --human:使用人类可读的格式显示大小和日期。
      • --no-trunc:显示完整信息,不做截断。
      • -q, --quiet:只显示镜像 ID 信息。
    • 样例
      docker history nginx:1.21.1
      
  10. docker import

    • 功能
      从归档文件中创建镜像。
    • 语法
      docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
      
    • 别名
      docker image import
      
    • 关键参数
      • -c:应用 Docker 指令创建镜像。
      • -m:提交时的说明文字。
    • 样例
      docker import my_ubuntu_v3.tar maxhou/ubuntu:v4
      
  11. docker image prune

    • 功能
      删除不使用的镜像。
    • 语法
      docker image prune [OPTIONS]
      
    • 关键参数
      • -a, --all:删除全部不使用的镜像。
      • --filter filter:指定过滤条件。
      • -f, --force:不提示是否删除。
    • 样例
      docker image prune
      
  12. 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: nginxports:- "80:80"db:image: postgres

使用 docker-compose up 启动多个容器。

5. Docker 网络

Docker 网络用于容器之间的通信。通过网络,容器可以相互访问,也可以与外部世界交互。默认情况下,Docker 会创建多个网络选项,如 bridgehostnone。用户可以创建自定义网络来实现不同的隔离和通信需求。

例如:使用 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 文件、传输文件、然后在目标机器上加载镜像。

步骤:

  1. 在源机器上保存 Docker 镜像

首先,使用 docker save 命令将 Docker 镜像保存为一个 tar 文件。

比如我们要迁移的镜像是 myapp:latest,可以执行以下命令:

docker save -o myapp_latest.tar myapp:latest
  1. 将 tar 文件传输到目标机器

将保存的 tar 文件传输到目标机器。可以使用 SCP、FTP、USB等方式来传输文件。

这里我们使用 SCP 将文件传输到目标机器的 /tmp 目录:

scp myapp_latest.tar user@target-machine:/tmp/
  1. 在目标机器上加载 Docker 镜像

当文件传输到目标机器上,就可以使用 docker load 命令来加载该镜像。

在目标机器上执行以下命令:

docker load -i /tmp/myapp_latest.tar

执行后有如下输出:

$ docker load -i /tmp/myapp_latest.tar
Loaded image: myapp:latest
  1. 验证镜像是否已加载成功

加载镜像后,可以使用 docker images 命令来查看是否镜像已经存在:

输出:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myapp               latest              d3b07384d113        2 hours ago         1.23GB

此时镜像 myapp:latest 已经成功加载到目标机器。

  1. 在目标机器上运行镜像

如果镜像加载成功,则可以在目标机器上运行该镜像:

docker run -d --name myapp_container myapp:latest

简单总结就是:

  1. 源机器:

    • docker save -o myapp_latest.tar myapp:latest 保存镜像。
    • 使用 scp 等方式传输 tar 文件到目标机器。
  2. 目标机器:

    • docker load -i /tmp/myapp_latest.tar 加载镜像。
    • 使用 docker images 验证镜像是否成功加载。
    • 使用 docker run 启动容器。

6.2 镜像存储的压缩与共享

  1. 拉取 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
  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
  1. 镜像压缩情况
    我们注意到 nginx:1.21.1 镜像的大小为 140MB 多,但在 Docker Hub 上查看时,镜像的大小大约为 50MB,这意味着镜像在传输时已经进行了压缩。仓库到本地的镜像文件越小越好,以减少网络带宽的消耗。

  2. 给镜像打多个 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 提示已存在的镜像层不会被重复上传,而是直接使用已有的层。

  1. 推送新镜像并发现已存在的层
    如果 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>总结

  1. 拉取镜像:通过 docker pull 拉取 nginx:1.21.1 镜像。
  2. 查看镜像大小:通过 docker images 查看本地镜像,发现镜像压缩。
  3. 推送多个标签:为一个镜像打多个标签,并推送到 Docker Hub,注意层的复用。
  4. 层复用:如果镜像层已存在,Docker 会挂载这些层而不是重复上传。

相关文章:

【Docker基础】全面解析 Docker 镜像:构建、使用与管理

文章目录 一、Docker 镜像&#xff08;Docker Image&#xff09;详解1.1 Docker 镜像的结构1.2 Docker 镜像的每一层&#xff08;Layer&#xff09;1.3 镜像的构建过程1.4 镜像的使用1.5 镜像的优势 二、为什么需要镜像三、镜像命令3.1 命令清单3.2 详细解释 四、docker 操作案…...

3. git config

文章目录 基本概述配置级别基本用法设置配置项查看配置项删除配置项 常用配置项 基本概述 git config 的作用是&#xff1a;设置用户信息、编辑器、别名、仓库行为等。 配置级别 级别作用范围配置文件路径命令选项仓库级别&#xff08;Local&#xff09;当前仓库.git/config…...

docker 运行自定义化的服务-前端

运行自定义化的前端服务 具体如下&#xff1a; ①打包前端项目&#xff0c;形成dist包 ②编写dockerfile文件&#xff0c;文件内容如下&#xff1a; # 基础镜像(镜像名:版本号TAG) FROM nginx:1.0 # 镜像作者和相关元数据 LABEL maintainer"Atb" \version"1.0…...

error: RPC failed; HTTP 408 curl 22 The requested URL returned error: 408

在git push时报错&#xff1a;error: RPC failed; HTTP 408 curl 22 The requested URL returned error: 408 原因&#xff1a;可能是推送的文件太大&#xff0c;要么是缓存不够&#xff0c;要么是网络不行。 解决方法&#xff1a; 将本地 http.postBuffer 数值调整到500MB&…...

JMH 基准测试实战:Java 性能对比的正确打开方式!

&#x1f4d6; 摘要 在Java开发中&#xff0c;我们经常需要比较不同实现方式的性能差异。但如何科学、准确地进行性能测试呢&#xff1f;本文将带你深入理解JMH&#xff08;Java Microbenchmark Harness&#xff09;工具&#xff0c;通过实战演示如何正确编写和运行基准测试&a…...

etf可以T+0交易吗?

在我国的A股市场中&#xff0c;部分ETF基金支持T0交易&#xff0c;这为投资者提供了更灵活的交易策略。 支持T0交易的ETF基金类型包括&#xff1a; 货币型ETF&#xff1a;主要投资于货币市场工具&#xff0c;如短期债券和银行存款&#xff0c;具有较高的流动性。 债券型ETF&…...

解决问题:Vscode 自动更新不匹配远程服务器版本

避免自动更新&#xff1a; 1. 打开&#xff1a;文件 - 首选项 - 设置 - 应用程序 - 更新&#xff1b; 2. 设置下列选项&#xff1a; 如果已自动更新&#xff0c;如何回退至原有的历史版本 &#xff1a; 去官网下载所需的历史版本&#xff0c;然后直接按流程安装&#xff0c;…...

【Leetcode-Hot100】盛最多水的容器

题目 解答 目的是求面积最大&#xff0c;面积是由两个下标和对应的最小值得到&#xff0c;因此唯一的问题就是如何遍历这两个下标。我采用begin和end两个变量&#xff0c;确保begin是小于end的&#xff0c;使用它们二者求面积&#xff0c;代码如下&#xff1a; 很不幸 出错了…...

FFMEPG常见命令查询

基本参数 表格1&#xff1a;主要参数 参数说明-i设定输入流-f设定输出格式(format) 高于后缀名-ss开始时间-t时间长度codec编解码 表格2&#xff1a;音频参数 参数说明-aframes设置要输出的音频帧数-f音频帧深度-b:a音频码率-ar设定采样率-ac设定声音的Channel数-acodec设定…...

欢迎来到 Codigger Store:Boby周边专区

亲爱的 Codigger 用户们&#xff0c;感谢你们一直以来的支持与热爱&#xff01;你们的每一次代码跳跃、每一次项目成功&#xff0c;都离不开你们对编程的热情和对 Codigger 的信任。为了回馈大家的厚爱&#xff0c;我们在 Codigger Store 中特别开设了 Boby 周边专区&#xff0…...

决策树模型

决策树(TDS) 注意1&#xff1a;决策树有很多种算法&#xff0c;比如&#xff1a;ID3算法&#xff0c;C4.5算法&#xff0c;CART算法&#xff0c;这三个算法的区别是选择最优划分属性的方法不同&#xff0c;第一个是根据信息增益来选&#xff1b;第二个是找出信息增益高于平均水…...

解锁深度学习激活函数

在深度学习的广袤天地里&#xff0c;激活函数宛如隐匿于神经网络架构中的神奇密码&#xff0c;掌控着模型学习与表达的关键力量。今天&#xff0c;就让我们一同深入探究这些激活函数的奇妙世界&#xff0c;揭开它们神秘的面纱。 一、激活函数为何不可或缺&#xff1f; 想象一…...

Kubernetes 深入浅出系列 | 容器剖析之容器安全

目录 1、容器真的需要privileged权限吗?一、什么是 --privileged 权限&#xff1f;二、privileged 的风险到底有多大&#xff1f;三、常见需求场景及更安全的替代方式四、如何判断容器是否真正需要特权&#xff1f; 2、不以 Root 用户运行容器&#xff0c;真的更安全吗&#x…...

Spring Boot应用中可能出现的Full GC问题

Full GC的原理与触发条件 原理 标记-清除&#xff1a;首先遍历所有对象&#xff0c;标记可达的对象&#xff0c;然后清除不可达的对象。复制算法&#xff1a;将内存分为两部分&#xff0c;每次只使用其中一部分。当这部分内存用完时&#xff0c;将存活的对象复制到另一部分&a…...

Maven 的安装与配置(IDEA)

2025/4/9 向 一、什么是Maven Maven 是一个基于项目对象模型&#xff08;Project Object Model&#xff0c;POM&#xff09;概念的项目构建工具&#xff08;所以就是一个工具&#xff09;&#xff0c;它主要用于自动化项目的构建过程&#xff0c;包括编译、测试、打包、部署等…...

软考中级-软件设计师 2022年下半年上午题真题解析:通关秘籍+避坑指南

&#x1f4da; 目录&#xff08;快速跳转&#xff09; 选择题&#xff08;上午题&#xff09;&#xff08;每题1分&#xff0c;共75分&#xff09;一、 计算机系统基础知识 &#x1f5a5;️&#x1f4bb; 题目1&#xff1a;计算机硬件基础知识 - RISC&#xff08;精简指令集计算…...

全栈开发套件Telerik DevCraft——赋能现代化应用构建

Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库&#xff0c;加快开发速度。Telerik DevCraft提供完整的工具箱&#xff0c;用于构建现代和面向未来的业务应用程序&#xff0c;目前提供UI for ASP.NET MVC、Kendo…...

Windows + vmware + ubuntu+docker + docker-android实现Android模拟器构建和启动

文章目录 引言编译启动过程玩下adb最后 引言 Windows vmware ubuntudockerdocker-android实现Android模拟器启动 编译启动过程 #下载docker-android git clone https://github.com/budtmo/docker-android.gitmaqiubuntu:~/docker-android$ git remote -v origin https://…...

远程团队协作效率低,如何优化

在远程工作的环境中&#xff0c;团队协作效率低下成为许多企业面临的一大挑战。随着全球化和技术进步&#xff0c;远程团队的出现成为企业的常态&#xff0c;但由于沟通不畅、任务管理不明确、缺乏团队凝聚力等问题&#xff0c;往往会影响团队的整体效率。为了优化远程团队的协…...

Oracle 19C 通过 ODBC 连接 SQL Server 数据库指南 (Red Hat 7)

前言 本指南详细说明如何在 Red Hat Enterprise Linux 7 系统上配置 Oracle 19C 通过 ODBC 连接 SQL Server 数据库。这种异构数据库连接方式称为 Oracle Heterogeneous Services,允许 Oracle 数据库直接访问非 Oracle 数据源。 系统要求 操作系统:Red Hat Enterprise Linu…...

【MYSQL从入门到精通】数据类型及建表

一些基础操作语句 1.使用客户端工具连接数据库服务器&#xff1a;mysql -uroot -p 2.查看所有数据库&#xff1a;show databases; 3.创建属于自己的数据库&#xff1a; create database 数据库名;create database if not exists 数据库名; 强烈建议大家在建立数据库时指定编…...

鸿蒙开发中的并发与多线程

文章目录 前言异步并发 (Promise和async/await)多线程并发并发能力选择耗时任务并发执行场景常见业务场景 常驻任务并发执行场景常见业务场景 传统共享内存并发业务长时任务并发执行场景常见业务场景 并发任务管理线程间通信同语言线程间通信&#xff08;ArkTS内&#xff09;线…...

ruby self

在 Ruby 中&#xff0c;self 是一个指向当前对象的特殊变量&#xff0c;它的值根据代码的上下文动态变化。理解 self 的指向是掌握 Ruby 面向对象编程的关键。以下是详细解析&#xff1a; 一、self 的核心规则 self 始终指向当前方法的执行者&#xff08;即调用方法的对象&…...

Kotlin 学习-集合

/*** kotlin 集合* List:是一个有序列表&#xff0c;可通过索引&#xff08;下标&#xff09;访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:&#xff08;字典&#xff09;是一组键值对。键是唯一的…...

封装方法的辨析

equals //字符串 str1.equals(str2); //list的两个实现类 list1.equals(list2); //map的两个实现类 //比较所有的键值对是否相同 map1.equals(map2); //数组&#xff08;包括string类型&#xff09; //比较内容是否相同 Arrays.equals(array1, array2); contains 基本都有…...

解决 IntelliJ IDEA 中 Maven 项目左侧项目视图未显示顶层目录问题的详细步骤说明

以下是解决 IntelliJ IDEA 中 Maven 项目左侧项目视图未显示顶层目录问题的详细步骤说明&#xff1a; 1. 切换项目视图模式 默认情况下&#xff0c;IDEA 的项目视图可能处于 Packages 模式&#xff0c;仅显示代码包结构&#xff0c;而非物理目录。 操作步骤&#xff1a; 点击…...

CMIP6数据分析与可视化、降尺度技术与气候变化的区域影响、极端气候分析

当前的CMIP6计划相较于前代模型&#xff0c;在空间分辨率、物理过程表达和地球系统组件耦合等方面均有显著提升。 一&#xff1a;气候变化研究的AI新视角 1、气候模型基础与全球气候模型&#xff08;GCM&#xff09; 全球气候&#xff08;环流&#xff09;模型的基本原理、发…...

如何精准控制大模型的推理深度

论文标题 ThinkEdit: Interpretable Weight Editing to Mitigate Overly Short Thinking in Reasoning Models 论文地址 https://arxiv.org/pdf/2503.22048 代码地址 https://github.com/Trustworthy-ML-Lab/ThinkEdit 作者背景 加州大学圣迭戈分校 动机 链式推理能显…...

1. Git 下载和安装

文章目录 Git 下载Git 安装&#xff08;以windows为例&#xff09;Git 使用&#xff08;以windows为例&#xff09; Git 下载 1.进 Git 官网 https://git-scm.com/downloads 2.选择对应的操作系统 3.选择对应的操作系统位数 Git 安装&#xff08;以windows为例&#xff09;…...

git回滚指定版本并操作

你可以通过以下步骤切换到第三个版本。根据你的需求&#xff0c;有两种主要方法&#xff1a; 方法 1&#xff1a;临时查看第三个版本&#xff08;不修改当前分支&#xff09; 适用于仅查看或测试旧版本&#xff0c;不保留后续修改&#xff1a; 找到第三个版本的提交哈希&#…...

FastAdmin和thinkPHP学习文档

介绍 - FastAdmin框架文档 - FastAdmin开发文档https://doc.fastadmin.net/doc目录结构 ThinkPHP5.0完全开发手册 看云ThinkPHP V5.0是一个为API开发而设计的高性能框架——是一个颠覆和重构版本&#xff0c;采用全新的架构思想&#xff0c;引入了很多的PHP新特性&#xff0c…...

通过HTTP协议实现Git免密操作的解决方案

工作中会遇到这样的问题的。 通过HTTP协议实现Git免密操作的解决方案 方法一&#xff1a;启用全局凭据存储&#xff08;推荐&#xff09; 配置凭证存储‌ 执行以下命令&#xff0c;让Git永久保存账号密码&#xff08;首次操作后生效&#xff09;&#xff1a; git config --g…...

git 查看某一文件夹下所有文件 修改记录

git: 如何查询某个文件或者某个目录的更新历史_git 查看指定文件夹的记录-CSDN博客 git log --follow path/to/your/file git log -p --follow path/to/your/file git log --stat --follow path/to/your/file这是最常用的方法&#xff0c;可以显示指定文件的所有提交历史…...

测试(一)

软件的生命周期&#xff1a; 需求分析——计划——设计——编码——测试——运行维护 常见的开发模型&#xff1a; 瀑布模型&#xff1a; 最基本的开发模型&#xff0c;绝大多数开发模型的基本框架。 特点&#xff1a;线性的开发流程 使用场景&#xff1a;需求固定&#xff…...

解决华硕主板Z890m下载ubuntu20.04后没有以太网问题

问题描述&#xff1a; 华硕主板Z890m下载双系统ubuntu20.04后&#xff0c;发现ubuntu不能打开以太网。 问题原因&#xff1a; 华硕主板的网卡驱动是r8125,而ubuntu20.04的驱动版本是r8169&#xff0c;所以是网卡驱动不匹配造成 解决方案 开机界面按下F2进入BOIS模式&#…...

从零推导飞机小扰动运动线性方程——0. 学习目录

第0期文章——学习目录 如图&#xff0c;本专栏将连载以下学习内容&#xff0c;带你从零开始学习飞机小扰动方程&#xff01;...

Agentic AI 干货!DeepSeek + OpenAI SDK 构建 Agent 实战

引言&#xff1a; DeepSeek-R1、OpenAI-o1 等具备内化的假设、反思、验证等优秀推理能力的 LLM 大型推理模型将 AI 发展推进到智能体 AI 时代&#xff0c;将使 AI Agent 迸发出远超上一代由外化的手搓式简单推理 Agent 不可比拟的发展势能。 在 GTC2025 大会上&#xff0c;英伟…...

【语法】C++的list

目录 为什么会有list&#xff1f; 迭代器失效&#xff1a; list和vector的迭代器不同的地方&#xff1a; list的大部分用法和vector都很像&#xff0c;例如push_back&#xff0c;构造&#xff0c;析构&#xff0c;赋值重载这些就不再废话了&#xff0c;本篇主要讲的是和vecto…...

Java接口性能优化面试问题集锦:高频考点与深度解析

1. 如何定位接口性能瓶颈&#xff1f;常用哪些工具&#xff1f; 考察点&#xff1a;性能分析工具的使用与问题定位能力。 核心答案&#xff1a; 工具&#xff1a;Arthas&#xff08;在线诊断&#xff09;、JProfiler&#xff08;内存与CPU分析&#xff09;、VisualVM、Prometh…...

基于STM32与应变片的协作机械臂力反馈控制系统设计与实现---5.2 工业机械臂系统性能测试全方案(专业工程级)

5.2 工业机械臂系统性能测试全方案(专业工程级) 一、测试体系架构设计 1.1 三级测试体系 #mermaid-svg-A55VxjZ7ENKNWAli {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-A55VxjZ7ENKNWAli .error-icon{fill:#55…...

VM——相机拍照失败

1、问题&#xff1a;相机频闪触发&#xff0c;在MVS中正常出图&#xff0c;在VM中出现拍照失败 2、解决&#xff1a; 1、首先排查网络设置&#xff08;巨帧是否设置&#xff09; 2、电脑的所有防火墙是否关闭 3、在MVS中恢复相机的设置参数为默认参数&#xff0c;删除VM中的全…...

图解力扣回溯及剪枝问题的模板应用

文章目录 选哪个的问题17. 电话号码的字母组合题目描述解题代码图解复杂度 选不选的问题78. 子集题目描述解题代码图解复杂度 两相转化77. 组合题目描述解题代码法一&#xff1a;按选哪个的思路法二&#xff1a;按选不选的思路 图解选哪个&#xff1a;选不选 复杂度 选哪个的问…...

Trae + LangGPT 生成结构化 Prompt

Trae LangGPT 生成结构化 Prompt 0. 引言1. 安装 Trae2. 克隆 LangGPT3. Trae 和 LangGPT 联动4. 集成到 Dify 中 0. 引言 Github 上 LangGPT 这个项目&#xff0c;主要向我们介绍了写结构化Prompt的一些方法和示例&#xff0c;我们怎么直接使用这个项目&#xff0c;辅助我们…...

模糊测试究竟在干什么

目录 1.软件漏洞和缺陷 2.模糊测试与传统测试 3.汽车领域中的模糊测试 4.常见工具总结 1.软件漏洞和缺陷 提单、上票、拒收&#xff0c;这是开发和测试的日常博弈。大多数时候&#xff0c;我们是根据自己对需求的理解来进行开发和测试&#xff0c;这基本是属于功能层级。 …...

【RTD200P04 MCAL 篇3】 S32M244 PWM PDB ADC控制

【RTD200P04 MCAL 篇3】 S32M244 PWM PDB ADC控制 一&#xff0c;文档简介二&#xff0c;PWMTRGMUXPDBADC 2ch 软件配置与实现2.1 软硬件版本平台2.2 MCAL工程以及模块配置2.2.1 Dio 模块配置2.2.2 Adc模块配置2.2.3 Mcu模块配置2.2.4 Platform模块配置2.2.5 Port模块配置2.2.6…...

03--Deepseek服务器部署与cjson解析

一、ollama部署deepseek模型 1、Ollama 是一个开源的本地大语言模型运行框架&#xff0c;专为在本地机器上便捷部署和运行大型语言模型&#xff08;LLM&#xff09;而设计。 Ollama 教程&#xff1a;从 0 到 1 全面指南 教程【全文两万字保姆级详细讲解】 -CSDN博客 1.下载o…...

实现抗隐私泄漏的AI人工智能推理

目录 什么是私人AI? 什么是可信执行环境? TEE 如何在 AI 推理期间保护数据? 使用 TEE 是否存在风险? 有哪些风险? Atoma 如何应对这些风险 为什么去中心化网络是解决方案 人工智能推理过程中还有其他保护隐私的方法吗? 私人人工智能可以实现什么? 隐私驱动的应…...

Kotlin 学习--数组

一、关于数组的基础知识和常用方式 /*** kotlin 数组* 使用arrayOf创建数组&#xff0c;必须指定数组的元素&#xff0c;可以是任意类型* */val arrayNumber arrayOf(1, 2, 3, 4)/*** 集合中的元素可以是任意类型* kotlin 中的Any 等价于 java 中的Object 对象的意思* */val a…...

Spring Boot 启动后自动执行 Service 方法终极指南

**导语​​&#xff1a;**在 Spring Boot 开发中&#xff0c;我们经常需要在应用启动后立即执行初始化任务&#xff08;如加载配置、预热缓存、启动定时任务&#xff09;。本文将深度解析 ​​5 种主流实现方案​​&#xff0c;包含完整代码示例、执行顺序控制技巧和避坑指南&a…...

STM32 HAL库之GPIO示例代码

LED灯不断闪烁 GPIO初始化&#xff0c;main文件中的 MX_GPIO_Init(); 也就是在 gpio.c文件中 void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOE_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOA_C…...