【Docker学习三部曲】—— 入门篇

Docker 入门

Docker 概述

1️⃣ 什么是 docker ?

Docker 是一种运行应用程序的平台,它可以使应用程序在容器中不受环境差异的影响进行部署和运行。Docker 的流行度越来越高,是因为它可以帮助在不同的开发者和开发团队之间实现代码的共享和协同开发,并且大大简化了应用程序的部署,提高了可移植性和可扩展性

2️⃣ Docker 为什么会出现?

Docker 的出现主要是为了解决旧有的应用程序部署模式的问题,传统方式是将应用程序和其依赖的软件库打包成一个安装程序并安装到目标计算机的操作系统上,这样会带来一些问题,例如:

(1)应用程序在不同的操作系统环境中可能无法运行,部署变得复杂;
(2)应用程序依赖的软件库可能会相互冲突,导致运行时出错;
(3)应用程序在部署过程中可能会影响宿主操作系统的其他应用程序的运行。

而 Docker 则是将应用程序及其依赖的软件库打包到一个容器中,容器中包含了应用程序的所有运行环境,可以在任何支持 Docker 的操作系统上运行,同时容器之间是相互隔离的,确保安装不同应用程序的容器不会相互影响。

Docker 的出现极大的简化了应用程序的部署和维护,提高了开发效率和运维效率,并且让应用程序的可移植性和可扩展性得到了大幅提升。

docker官网、文档、仓库

3️⃣ docker 与 传统虚拟机的区别:

Docker 和虚拟机(VM)都是在不同的环境中运行应用程序的技术,但是它们有一些本质的区别。

(1)虚拟机是虚拟化操作系统,而 Docker 是容器化平台

虚拟机通过在物理计算机上安装虚拟化软件来模拟一个完整的计算机系统,包括操作系统、硬件和所有运行所需的软件。而 Docker 是容器化平台,可以实现应用程序在隔离的运行环境中运行,而不需要模拟一个完整的操作系统。

(2)虚拟机需要更多的系统资源

由于虚拟机模拟了完整的计算机系统,因此它需要更多的系统资源,例如 CPU、内存和存储空间。相比之下,Docker 可以在更轻量级的容器中运行应用程序,并且可以共享主机操作系统的资源,因此 Docker 通常需要更少的系统资源。

(3)Docker 更快地启动和运行应用程序

由于 Docker 不需要模拟整个操作系统,它的启动时间通常比虚拟机更短,并且可以快速地创建、销毁和重新部署容器。这使得 Docker 更适合于需要频繁部署和更新的环境,例如持续集成和持续交付(CI/CD)管道。

(4)Docker 更易于管理和部署应用程序

在 Docker 中,应用程序和其依赖项被打包在一个镜像中,并可以轻松地在不同的环境中部署和迁移。使用 Docker 还能够迅速地在多台主机上扩展应用程序。
综上所述,虚拟机虚拟化操作系统,能够隔离运行环境并支持多个操作系统,但需要更多系统资源启动和运行。而 Docker 则采用容器技术隔离应用程序,快速启动并易于管理和部署。

4️⃣ DevOps(Development和Operations)开发、运维

  • 是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合

  • 应用更快速的交付和部署

    • 传统:一对帮助文档,安装程序。

    • Docker:打包镜像发布测试一键运行。

  • 更便捷的升级和扩缩容

    • 使用了 Docker之后,我们部署应用就和搭积木一样,项目打包为一个镜像,扩展服务器A、服务器B
  • 更简单的系统运维

    • 在容器化之后,我们的开发,测试环境都是高度一致的
  • 更高效的计算资源利用

    • Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例
    • 服务器的性能可以被压榨到极致。

5️⃣ docker 的基本组成

Docker 是一个开源的容器化平台,由一系列组件组成,这些组件共同协作来创建、管理和运行容器。Docker 的基本组成如下:

  • Docker 客户端和服务端

    • Docker 客户端负责与 Docker 服务端通信,执行 Docker 命令,申请容器、镜像等;
    • Docker 服务端则管理和控制所有的 Docker 容器和镜像。
  • Docker 镜像(Image)

    • Docker 镜像是用来创建 Docker 容器的模板。
    • 它包含应用程序代码、库、运行环境和配置文件,类似于虚拟机的镜像。
    • Docker 镜像可以通过 Dockerfile 或从 Docker 中央仓库中拉取构建。
  • Docker 容器(Container)

    • Docker 容器是 Docker 镜像的实例化运行时,它是一个分离的环境,包含了应用程序和其依赖项,能够独立运行于 Docker 主机上。
  • Docker Registry

    • Docker Registry 是一个中央存储库,用于存储 Docker 镜像。
    • Docker Hub 是 Docker 官方提供的 Registry,也可以通过私有 Registry 将 Docker 镜像推送和拉取到远程服务器上。
  • Docker Compose

    • Docker Compose 是一个用于定义和运行多个 Docker 容器的工具,它使用 YAML 文件来定义整个应用程序的服务、网络和卷等,使得可以轻松地部署和扩展多个 Docker 容器。
  • Docker Swarm

    • Docker Swarm 是 Docker 官方提供的容器编排工具
    • 它可以将多个 Docker 主机组成一个集群,使用 Docker API 进行编排和管理 Docker 容器,在集群中自动管理容器的调度、复制、伸缩等。

综上所述,Docker 的基本组成包括Docker 客户端和服务端、Docker 镜像、Docker 容器、Docker Registry、Docker Compose 和 Docker Swarm 等组件。这些组件可以帮助开发人员实现容器化部署、管理和调度。

Docker 安装

此处我们以阿里云ESC服务器CentOS系统安装Docker为例
点击查看 Docker安装官方文档

1️⃣ 准备工作:

  • 一台阿里云ESC服务器 【学生可以免费使用六个月】
  • 服务器的操作系统是 CentOS7
  • 一个安全终端模拟软件,此处使用的是 XShell

通过 uname -r 可以查看我们Linux的系统内核,通过 cat /etc/os-release 可以查看当前Linux的版本信息

在这里插入图片描述
如果我们之前安装了 Docker,想要重新安装需要先卸载原来的

yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

2️⃣ 开始安装

  • docker-ce: Docker 守护进程,这是完成所有管理工作的部分 【ce代表社区版、ee代表企业版】
  • docker-ce-cli: 用于控制守护进程的 CLI 工具
  • containerd.io: 与 OS API 接口的守护进程,本质上将 Docker 与 OS 分离,还为非 Docker 容器管理器提供容器服务
# 下载需要的安装包
yum install -y yum-utils

# 设置使用国内的镜像的仓库
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
# 更新yum软件包索引
yum makecache fast

# 安装docker相关的东西
yum install docker-ce docker-ce-cli containerd.io

# 启动docker
systemctl start docker

3️⃣ 测试

# 查看docker版本
docker version

在这里插入图片描述

# 运行 hello-world 镜像
docker run hello-world

在这里插入图片描述

  • 运行流程说明:
    • docker 先会在我们的本地去查找镜像,如果有就运行镜像,没有会到公共官方仓库去寻找
    • 远程仓库有这个镜像,那么就会将这个镜像下载到本地,然后运行镜像
    • 远程仓库没有那么就会报错

在这里插入图片描述

# 查看本地下载的镜像
docker images

在这里插入图片描述

4️⃣ 配置镜像加速

  • 因为我使用的是阿里云服务器,所以就使用阿里云提供的免费镜像服务 【可以帮助 Docker 用户快速地拉取 Docker 镜像

  • 来到阿里云官网,直接搜索 容器镜像服务 -> 左下角找容器加速器 -> 查看操作文档

    # 创建目录
    sudo mkdir -p /etc/docker
    # 编辑配置文件
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://jtbaky9r.mirror.aliyuncs.com"]
    }
    EOF
    # 重启服务
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    
  • 阿里云镜像加速为什么只能使用自己的账号呢?

    • 这是因为使用镜像加速服务的用户需要拥有访问镜像加速服务的权限。
    • 阿里云要求用户登录后方才可以访问阿里云提供的服务,这样可以保证服务的稳定性和安全性,并且可以为用户提供定制化服务。
    • 此外,只有登录的用户才能享受阿里云实时更新的 Docker 镜像。
  • 可以配置多个镜像加速地址,彼此用逗号分隔开

Docker 原理

  • Docker是一种开源的容器化平台,能够在容器中运行应用程序。

  • Docker将应用程序和其依赖项封装在一个小而轻量级的容器中,使应用程序更容易部署、迁移和管理。

  • Docker的工作原理基于Linux操作系统的特性和技术,主要包括以下几个方面:

    • Namespace和cgroup技术
      • Docker使用Linux的 Namespacecgroup 技术对资源进行隔离和管理。
      • Namespace技术可以隔离文件系统、网络、进程、用户等系统资源,使不同容器中的进程拥有独立的资源环境。
      • cgroup技术可以限制容器中进程的资源利用率,比如CPU、内存、磁盘IO等。
    • Docker镜像
      • Docker镜像是一个只读的分层文件系统,包含了一个应用程序的所有依赖项和运行环境。
      • Docker镜像可以通过Dockerfile定义镜像的构建过程,也可以从Docker Hub等公共或私有仓库中获取已有的镜像。
    • Docker容器
      • Docker容器是基于Docker镜像创建的可读写的运行实例,包括了应用程序、应用程序的依赖项、运行时环境和容器配置等。
      • Docker容器可以启动、停止、删除、移动和复制等。
    • Docker守护进程
      • Docker守护进程是Docker引擎的核心组件,负责管理和控制Docker的运行。
      • Docker守护进程可以通过REST API和CLI进行交互,并将Docker镜像、容器和其他资源存储在本地或远程的Docker注册表中。
    • Docker网络
      • Docker网络是一种虚拟网络,可以在不同容器之间提供网络通信。
      • Docker网络支持桥接网络、主机网络、覆盖网络等多种网络模式,并支持多种网络驱动程序,如Docker自带的bridge驱动、host驱动、overlay驱动、macvlan驱动等。
  • 总之,Docker的工作原理采用了诸多Linux操作系统的技术和特性,通过Docker镜像和容器实现应用程序的封装和运行,Docker守护进程负责管理与控制,并通过Docker网络提供容器间的网络连接


Docker 命令

点击跳转 官方命令帮助文档

帮助命令

# 查看 docker 版本
docker version

在这里插入图片描述

# 查看 docker 的系统信息

在这里插入图片描述

# 查看指定命令的帮助命令
docker 命令 --help
# 查看所有命令
docker --help

在这里插入图片描述

镜像命令

1️⃣ 查看本地主机上的 docker 镜像

docker images
docker image ls
  • 名词解释:
    • Repository 代表镜像名
    • Tag 代表镜像版本
    • Image ID 代表镜像ID
    • Create 代表创建时间
    • Size 代表镜像大小
  • 常用可选项:
    -a 或 --all:列出所有的镜像,包括中间层镜像;
    -q 或 --quiet:仅显示镜像的唯一标识符 ID;
    --filter:根据给定的条件过滤镜像;
    --format:使用 Go 模板格式化输出结果;
    --digests:显示镜像的摘要信息;
    --no-trunc:显示镜像 ID 的完整长度;
    --no-squash:不压缩中间层镜像(在构造镜像时重要)。
    

在这里插入图片描述

2️⃣ 搜索 docker 镜像

docker search 镜像名
  • 名词解释:
    • Name 镜像名称
    • Description 镜像说明
    • Stars 镜像收藏量
    • Official 是否为官方
    • Automated 是否自动构建

在这里插入图片描述

我们可以通过添加 --filter 选项来筛选镜像,比如我们筛选 stars大于 3000 的

docker search -f=stars=3000

在这里插入图片描述
3️⃣ 拉取镜像到本地

docker pull 镜像名 [:tag (版本,不指定就是最新版本)]

在这里插入图片描述
4️⃣ 删除镜像

# 删除指定ID的镜像 [通过空格分隔多个镜像ID可以删除多个镜像]
docker rmi -f 镜像ID
# 删除本地全部镜像
docker rmi -f $(docker images -aq)

容器命令

  • 我们是基于镜像来创建容器的 【可以将镜像理解为VM,容器就是VM上跑的单个Linux】
  • 所以我们下载一个 CentOS 镜像来完成案例演示
docker pull centos

在这里插入图片描述
1️⃣ 新建容器并启动

docker run 镜像名/镜像ID
  • 可选参数:
    • --name="Name" 容器名字,用来区分不同容器
    • -d 以后台的方式运行
    • -it 使用交互方式运行,进入容器查看内容
    • -p 指定容器的端口
      • -p ip:主机端口:容器端口
      • -p 主机端口:容器端口 常用
      • -p 容器端口
      • 容器端口
    • -P 随机指定端口

在这里插入图片描述

  • 我们需要知道,在第一次根据镜像创建容器时,使用镜像名或镜像ID都可以
    在这里插入图片描述
  • 说一下 run 和 start 启动容器有什么区别?
    • Docker run 命令用于创建一个新的容器并启动它
    • Docker start 命令用于启动已经创建好的容器

2️⃣ 查看正在运行的容器

docker ps
  • 可选参数:
    • 默认会列出当前正在运行的容器
    • -a 会列出当前正在运行的容器和历史运行过的容器
    • -n=x 会列出最近创建的x个容器
    • -q 只显示容器的编号

在这里插入图片描述

3️⃣ 退出容器

# 进入容器中,使用这个命令退出并关闭容器
exit
# 容器不停止退出容器
Ctrl + P + Q

在这里插入图片描述

4️⃣ 删除容器

# 删除指定的容器
docker rm 容器ID
# 处于运行状态的容器可以强制删除
docker rm -f 容器ID
# 删除本地所有的容器
docker rm -f ${docker ps -aq}
# 删除所有容器
docker ps -a -q | xargs docker rm

在这里插入图片描述

5️⃣ 启动和停止容器

# 启动我们已经创建的容器
docker start 容器ID
# 重启容器
docker restart 容器ID
# 停止当前正在运行的容器
docker stop 容器ID
# 强制停止当前容器
docker kill 容器ID

在这里插入图片描述

常用命令

1️⃣ 后台创建并启动命令

docker run -d 镜像名|镜像ID
  • 我们发现这种通过后台创建并启动的容器会自动关闭
    • 因为docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止

在这里插入图片描述
2️⃣ 查看日志

要查看 Docker 容器的日志,可以使用 docker logs 命令用于查看日志输出
在这里插入图片描述

可以有选择性的输出容器中的标准输出、标准错误或者完整的日志文件。

(1)下面是 docker logs 命令的基本语法:docker logs [OPTIONS] CONTAINER

  • 其中,CONTAINER 参数是要查看日志的容器名称或 ID,OPTIONS 参数是命令行选项。常用的选项包括:

    • -f 或 --follow:类似于 Unix 的 tail 命令,实时滚动显示日志输出,而不是显示完整的日志文件;
    • --tail:仅显示最后的若干行日志信息,可以指定显示的行数;
    • --since 和 --until:显示指定时间范围内的日志信息;
    • --timestamps:显示时间戳信息;
    • --details:显示详细的容器信息。

(2)下面是一些 docker logs 命令的示例:

# 这个命令将实时输出名为 my_container_name 容器的日志信息
docker logs -f my_container_name
# 这个命令将输出名为 my_container_name 容器的最后 10 行日志信息
docker logs --tail 10 my_container_name
# 这个命令将输出名为 my_container_name 容器在 2022 年 1 月 1 日之后生成的所有日志信息
docker logs --since 2022-01-01 my_container_name

3️⃣ 查看容器中的进程信息

docker top 容器ID
  • 参数说明:
    • UID 代表进程拥有者用户ID
    • PID 代表当前进程号
    • PPID 代表当前进程的父进程号
    • C 代表CPU使用资源百分比
    • STIME 代表系统启动时间
    • TTY 代表进程使用的控制台
    • TIME 代表CPU使用时间
    • CMD 代表所下达的指令

在这里插入图片描述

4️⃣ 查看镜像元数据

docker inspect 容器ID

在这里插入图片描述

5️⃣ 进入当前正在运行的容器

# 进入指定的容器并开启一个新的终端(常用)
docker exec -it 容器ID /bin/bash

在这里插入图片描述

# 进入指定容器正在执行的终端
docker attach 容器ID

在这里插入图片描述
6️⃣ 将容器中的文件拷贝到主机上

# 当前我就在容器中,所以我创建一个 zwh.java 文件
cd /home
touch zwh.java
# 退出容器,使用exit退出会关闭容器,但是无论它是否运行容器在数据就在
exit
# 将我们指定容器中的指定文件拷贝到指定目录
docker cp 容器ID:文件路径 保存路径

在这里插入图片描述

命令小结

在这里插入图片描述

# 当前 shell 下 attach 连接指定运行的容器
attach Attach to a running container
# 通过 Dockerfile 定制镜像
build Build an image from a Dockerfile
# 提交当前容器为新的镜像
commit Create a new image from a container changes
# 从容器中拷贝指定文件或目录到宿主机中
cp Copy files/folders from the containers filesystem to the host path
# 创建一个新的容器,但不启动容器
create Create a new container
# 查看 docker 容器变换
diff Inspect changes on a container's filesystem
# 从 docker 服务获取容器实时事件
events Get real time events from the server
# 在已存在的容器上运行命令
exec Run a command in an existing container
# 导出容器的内容流作为一个 tar 归档文件 [对应 import]
export Stream the contents of a container as a tar archive
# 展示一个镜像形成历史
history Show the history of an image
# 列出系统当前镜像
images List images
# 从 tar 包中的内容创建一个新的文件系统影响 [对应export]
import Create a new filesystem image from the contens of tarball
# 显示系统相关信息
info Display system-wide infomation
#查看容器详细信息
inspectt Return low-leve1 information on a container
# kill 指定 docker 容器
kill kill a running container
# 从一个 tar 包中加载一个镜像 [对应save]
load Load an image from a tar archive
# 注册或登录一个 docker 源服务器
login Register or Login to the docker registry server
# 从当前 Docker registry 退出
logout Log out from a Docker registry server
# 输出当前容器日志信息
logs Fetch the logs of a container
#查看映射端口对应的容器内部源端
port  Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
# 暂停容器
pause Pause all processes within a container
# 列出容器列表
pas List containers
# 从 docker 镜像源服务器拉取指定镜像或者库镜像
pull Pull an image or a repository from the docker registry server
#推送指定镜像或者库镜像至docker源服务器
push Push an image or a repository to the docker registry server
#重启运行的容器
restart Restart a running container 
# 移除一个或者多个容器
rm Remove one or more containers
# 移除一个或多个镜像[无容器使用该镜像才可除,否则需删除相关容器才可继续 或 -f 强制删除] 
rmi Remove one or more images
# 创建一个新的容器并运行一个命令
run Run a command in a new container 
# 保存一个镜像为一个tar包[对应load] 
save Save an image to a tar archive
# 在docker hub中搜索镜像 
search Search for an image on the Docker Hub
# 启动容器 
start Start a stopped containers
#停止容器 
stop stop a running containerstag
# 帮给源中镜像打标签
tag Tag an image into a repository 
# 查看容器中运行的进程信息
top Lookup the running processes of a container
# 取消暂停容器
unpause Unpause a paused container 
# 查看docker版本号 
version Show the docker version information
# 截取容器停止时的退出状态值
wait Block until a container stops,then print its exit code

作业练习

1️⃣ 作业一:使用 Docker 安装 Nginx

# 查找镜像
docker search nginx

在这里插入图片描述
在这里插入图片描述

# 拉取镜像到本地
docker pull nginx

在这里插入图片描述

# 开启我们的nginx
docker run -d --name nginx01 -p 3344:80 nginx
  • 参数说明:
    • -d 代表创建一个守护式容器在后台运行
    • --name 代表给我们的容器起的名字
    • -p port1:port2 代表暴露端口号
      • port1 是外部端口号
      • port2 是nginx内部端口号

在这里插入图片描述

  • 端口暴漏的关系:

在这里插入图片描述

# 查看 nginx 是否成功访问 [curl 命令用于在命令行中与 Web 服务器进行数据传输]
crul localhost:3344

在这里插入图片描述
通过浏览器访问测试

在这里插入图片描述

# 进入到我们的 nginx 容器中
docker exec -it nginx01 /bin/bash
# whereis 命令主要用于定位可执行文件(除shell 内置命令外)、源代码文件、帮助文件在文件系统中的位置
whereis nginx
# 查看一下我们 nginx 配置文件
ls /etc/nginx
# 退出我们的 nginx 容器 [和以往不同,此时退出并不会直接关闭 nginx 容器]
exit
# 查看我们当前运行的容器 [发现 nginx 果然还在运行]
docker ps
# 关闭我们nginx的容器 [此时我们通过web端已经访问不到了]
docker stop nginx01

在这里插入图片描述

2️⃣ 作业二:使用 Docker 安装 Tomcat

# 启动 tomcat
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 进入tomcat
docker exec -it tomcat01 /bin/bash
# 我们发现 webapps 下没有任何文件
ls webapps
# 将 webapps.list 目录下的文件拷贝到我们 webapps 目录下
cp webapps.list/* webapp

在这里插入图片描述
再次访问浏览器,发现可以成功访问到我们 tomcat 的首页了
在这里插入图片描述

3️⃣ 作业三: 使用 Docker 部署 ElasticSearch

# 启动 ElasticSearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 查看是否成功启动
curl localhost:9200
# 关闭 ElasticSearch [这个应用是非耗内存]
exit
docker stop elasticsearch
# 查看 cpu 的使用情况
docker stats
# 我们可以在创建并启动前添加内存限制
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

Docker 可视化

  • 通过借助 portainer 来完成 Docker 的可视化 【这个工具并不常用】

  • 在我们 Docker 中下载并启动我们的 portainer 容器

    docker run -d -p 8088:9000 \
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
    
  • 然后再我们的浏览器中就可以通过 IP:8080 访问,来到首页后我们设置密码登录,然后选择本地

在这里插入图片描述

  • 可以更直观的显示我们 Docker 的资源使用情况

在这里插入图片描述


Docker 镜像

Docker镜像是Docker容器的基础,可以视为虚拟机的硬盘映像。它是一个轻量级的、可移植的打包文件,其中包含运行特定应用程序所需的全部代码、运行时、库、设置和依赖项。 Docker镜像可以在不同的主机、环境和操作系统上部署,并且可以轻松地创建、分享和部署。

Docker镜像是通过Dockerfile定义的。 Dockerfile是一个文本文件,其中包含一系列指令,用于构建Docker镜像,例如从哪个基础镜像开始构建、安装哪些软件包、设置环境变量等。 Dockerfile用于构建Docker镜像时执行自动化构建步骤。

Docker镜像可以存储在Docker Hub等公共镜像仓库上,也可以存储在私有仓库中。可以根据需要将Docker镜像推送到仓库并从仓库拉取。利用Docker镜像,开发者和运维人员可以轻松部署和管理应用程序,从而使应用程序的发布和更新变得更加简单和可靠。

Docker 镜像加载原理

1️⃣ UnionFS 联合文件系统

(1)什么是联合文件系统?

  • 是一种分层、轻量级并且高性能的文件系统
  • 也成为联合挂载,是一种在操作系统中将多个文件系统合并成一个逻辑的文件系统的技术。

(2)联合文件系统有哪些性质?

联合文件系统由一组分离的文件系统组成,它们被挂载到同一个目录下,每个文件系统都能够提供自己的文件和子目录。当用户访问此目录时,文件系统会逐个检查它们的目录和文件,以找到匹配的文件或子目录。如果两个或多个文件系统都包含相同的文件或目录,联合文件系统将它们合并以创建一个联合视图。

联合文件系统的优点是它可以使用较少的物理空间来存储多个文件系统。因为联合文件系统仅存储差异,即仅存储每个文件系统的更改或添加(属于可写的文件系统),而不存储所有原始数据。这使得联合文件系统非常适合使用容器化技术,如Docker,因为可以在容器之间共享相同的文件系统,从而减少存储空间和加快容器的启动速度。

一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统盈加起来,这样最终的文件系统会包含所有底层的文件和目录

2️⃣ 镜像加载原理

在这里插入图片描述

  • Docker镜像加载涉及到多个层面的技术,包括Linux的联合文件系统及Docker自身的功能。其具体过程可以简单概括如下:

    • Docker拉取镜像
      • Docker需要从镜像仓库中获取镜像的信息和相应的layers
      • 这可以通过执行docker pull [image-name] 命令完成,其中包括从仓库下载镜像的元数据及layers。
    • Docker加载镜像的层
      • Docker将每个镜像的层叠加在一起,逐个加载,通常从最新的层开始加载。
      • 每个层都被视为“可写层”,并根据需要进行更改,如添加或编辑文件。
      • 在加载时,镜像的每一层都会覆盖之前的层,如果在早期层中有相同的文件,从而构建完全的可读可写的文件系统结构。
    • 基础镜像
      • Docker镜像是基于一个基础镜像创建的,Docker将“基础镜像”(基础层)在连接和堆叠之前加载。
    • 链接层
      • 当Docker加载镜像时,它针对每个新的’commit’都创建一层来存储在容器中应用程序的更改。
      • 这个commit被称为新层(新可写层),而每个可写层都是映射到原始镜像的只读层,这样就可以隔离更改。
    • 联合文件系统
      • 所有这些层都是通过联合文件系统拼接在一起。
      • 使用联合文件系统,Docker将每个镜像的更改与基础镜像合并为单个文件系统结构。
  • Docker镜像加载的本质是一个文件系统的栈,其中每个层都是可读可写的,为最终容器提供了虚拟文件系统。

  • 镜像的上一层可以增量地覆盖下一层中包含的文件或目录的文件和目录,以便将其添加到可访问的文件层次结构中,这是Docker可以构建出高度可重用,可移植的容器的根本原因。

Docker 分层的理解

1️⃣ 分层的镜像

根据我们之前下载镜像我们可以发现,资源是一层一层进行下载的
在这里插入图片描述
为什么 Docker 要采用这种分层的结构呢?

  • 最大的好处,我觉得莫过于资源共享
  • 比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像
  • 同时内存中也只需要加载一份base镜像
  • 这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享

通过 docker image inspect 镜像名|镜像ID 指令可以查看镜像的详细信息,里面包含分层的信息 【我们以nginx为例】

在这里插入图片描述
2️⃣ 案例分析

  • 所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或添加新的内容时,就会在当前镜像层之上,创建新的镜像层

(1)假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当前已经包含3个镜像层

在这里插入图片描述

(2)在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合

在这里插入图片描述
(3)下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版

在这里插入图片描述

(4)上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中

在这里插入图片描述

Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统

Linux 上可用的存储引擎有 AUFS、 Overlay2、 Device Mapper、Btrfs 以及 ZFS
顾名思义,每种存储引擎都基于 Linux中对应的件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。

DockerWindows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW

(5)特点:

  • Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部

  • 这一层就是我们通常说的容器层,容器之下的都叫镜像层!:

在这里插入图片描述

3️⃣ 提交镜像

docker commit 命令可以将一个运行中的 Docker 容器打包成一个新的 Docker 镜像
它主要的作用是在容器中安装新的软件或修改配置文件之后,把这些修改保存下来,形成一个新的镜像

  • docker commit 命令的语法如下:
    docker commit [OPTIONS] CONTAINER NEW_IMAGE[:TAG]

  • 其中:

    • OPTIONS
      • 可以包括 -a(作者信息)
      • -c(在运行期间设置容器配置信息)
      • -m(提交时添加说明)等选项
    • CONTAINER:需要被提交的容器 ID
    • NEW_IMAGE:新生成的镜像名称
    • :TAG:可以为新生成的镜像指定一个标签,如果没有指定则默认为 latest
  • 例如,执行以下命令将运行中的名为 mycontainer 的容器提交为一个名为 myimage 的新镜像:docker commit mycontainer myimage

执行完后,myimage 就成为了一个新的镜像,并包含了容器中的所有修改。之后可以使用 docker run 命令来启动这个新的镜像,或者使用 docker push 命令将其传送到远程 Docker 仓库中。

需要注意的是,使用 docker commit 命令生成镜像时会保存容器内的所有修改,包括不必要的文件和未清理的临时文件,所以最好在容器清理后再提交镜像。同时,也需要避免通过 docker commit 命令生成过多镜像,最好还是通过使用 Dockerfile 来自动化地构建和生成镜像

4️⃣ 案例演示创建一个镜像

  • 之前我们说过,tomcat 容器构建成功后 webapps下是没文件的,那些文件都在 webapps.dist
  • 我们就将这些文件直接复制到webapps目录下,然后打包成镜像,这样别人用我们的这个镜像就可以直接访问到 tomcat 的首页
# 根据镜像创建并启动 tomcat 容器
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 进入到我们的 tomcat 容器
docker exec -it tomcat01 /bin/bash
# 将我们webapps.dist目录下的内容拷贝到webapps目录下
cp -r webapps.dist/* webapps
# 退出我们的tomcat
exit
# 将我们的tomcat容器打包成镜像
docker commit -m="add webapps app" -a="zwh" 容器ID 镜像名

在这里插入图片描述
可以看到我们打包的 tomcat02 镜像比官方的大了一点

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bow.贾斯汀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值